C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.80073 の関連記事表示

<< 0 >>
■80073  バックグランドワーカーとグローバル変数
□投稿者/ 初心者123 -(2016/06/08(Wed) 20:41:39)

    分類:[C#] 

    はじめましてバックグランドワーカ、C#初心者です。よろしくお願い致します。
    環境はVS2013 C# WindowsFormアプリケーションです。

    メインフォームとBGWスレッドの間でデータ受け渡しが多いため、
    グローバル変数でやり取りすることを考えており、BGW使い方を含めて基礎動作の確認を行っております。

    メイン側でグローバル変数、変数1、変数2を定義し、
    メインフォームのタイマーで変数1を加算しています。
    BGWスレッドで変数1の値を比較し変数2の計算を行っているのですが
    計算結果が期待した値になりません。
    実際はこのような処理ではないですが、現象再現のため簡略化したプログラムが下記になります。
    実際はもっと多くのデータやり取りですが、基本的には変数操作はBGW側で行い、
    メイン側はほとんどが表示や参照だけであるため排他制御の必要もないと考えております。
    基本的な問題かと思いますが御教授願います

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    namespace WindowsFormsApplication1
    {

    public partial class Form1 : Form
    {

    long Cnt1 = 0; // 変数1
    long Cnt2 = 1; // 変数2

    public Form1()
    {
    InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    timer1.Enabled = true;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
    Cnt1++; // メインフォームのタイマーで変数1を加算
    }


    private void btnBGWSta_Click(object sender, EventArgs e)
    {
    bgW1.RunWorkerAsync();
    }

    private void btnBGWStp_Click(object sender, EventArgs e)
    {
    bgW1.CancelAsync();
    }

    //=================================================================================
    // BGW Main
    //=================================================================================
    private void bgW1_DoWork(object sender, DoWorkEventArgs e)
    {
    while (true)
    {
    if (bgW1.CancellationPending)
    {
    e.Cancel = true;
    break;
    }
    if (Cnt1 == 100) // 変数1の値を比較
    {
    Cnt2 = Cnt2 * 2; // 変数2を計算 初期値1であるため結果2を期待しているが2048になる
    }
    System.Threading.Thread.Sleep(1);
    }
    }

    }
    }
親記事 /過去ログ136より / 関連記事表示
削除チェック/

■80075  Re[1]: バックグランドワーカーとグローバル変数
□投稿者/ Jitta -(2016/06/08(Wed) 20:51:19)
    No80073 (初心者123 さん) に返信
    Cnt1が100である時間が8秒あるから。
    1度2倍したら、次のトリガーまでifの条件が成立したらいけないよね。
記事No.80073 のレス /過去ログ136より / 関連記事表示
削除チェック/

■80080  Re[2]: バックグランドワーカーとグローバル変数
□投稿者/ 初心者123 -(2016/06/08(Wed) 22:12:16)
    No80075 (Jitta さん) に返信
    > ■No80073 (初心者123 さん) に返信
    > Cnt1が100である時間が8秒あるから。
    > 1度2倍したら、次のトリガーまでifの条件が成立したらいけないよね。

    どうもありがとうございます。気付きました。BGWに何かあるのかとかばかり考えていました。
記事No.80073 のレス / END /過去ログ136より / 関連記事表示
削除チェック/

■80078  Re[1]: バックグランドワーカーとグローバル変数
□投稿者/ shu -(2016/06/08(Wed) 21:23:15)
    No80073 (初心者123 さん) に返信

    https://msdn.microsoft.com/ja-jp/library/d00bd51t(v=vs.110).aspx

    Sleepの引数はms単位なので
    1msスリープしたらループを回るので
    Timer1_tickが発生するまでの間条件が変わらない状態となります。

    別にフラグなど設けるなどして繰り返し足されるのを抑制する必要があります。
記事No.80073 のレス /過去ログ136より / 関連記事表示
削除チェック/

■80081  Re[2]: バックグランドワーカーとグローバル変数
□投稿者/ 初心者123 -(2016/06/08(Wed) 22:13:03)
    No80078 (shu さん) に返信
    > ■No80073 (初心者123 さん) に返信
    >
    > https://msdn.microsoft.com/ja-jp/library/d00bd51t(v=vs.110).aspx
    >
    > Sleepの引数はms単位なので
    > 1msスリープしたらループを回るので
    > Timer1_tickが発生するまでの間条件が変わらない状態となります。
    >
    > 別にフラグなど設けるなどして繰り返し足されるのを抑制する必要があります。

    どうもありがとうございます。気付きました。BGWに何かあるのかとかばかり考えていました。
記事No.80073 のレス / END /過去ログ136より / 関連記事表示
削除チェック/

■80079  Re[1]: バックグランドワーカーとグローバル変数
□投稿者/ なちゃ -(2016/06/08(Wed) 22:06:49)
    やや別の観点から。
    スレッド間で正しく変数を共有するには、それなりにルールがあります。
    仮に今のプログラムがロジック的には正しかったとしても、スレッド感では正しい共有の仕方をしないと、正しく動作する保証はなくなります。

    例えば、タイマーで加算した変数の値がバツマクグラウンドスレッド側で見えないなど。

    現実には.NETの場合、あまりこういうことは起こりにくい実装にはなっていますが、正しい方法を知っておくに越したことはありません。
    たとえば今の実装では、おそらくバックグラウンドワーカーへのアクセスでメモリ同期が働いてうまく動作します。
    が、ある意味たまたまのようなもので、それに依存するのは望ましくはありません。
    ※その前にSleepがきいてると思いますが、これはなくなったりする想定で
記事No.80073 のレス /過去ログ136より / 関連記事表示
削除チェック/

■80083  Re[2]: バックグランドワーカーとグローバル変数
□投稿者/ 初心者123 -(2016/06/08(Wed) 22:17:49)
    No80079 (なちゃ さん) に返信
    > やや別の観点から。
    > スレッド間で正しく変数を共有するには、それなりにルールがあります。
    > 仮に今のプログラムがロジック的には正しかったとしても、スレッド感では正しい共有の仕方をしないと、正しく動作する保証はなくなります。
    >
    > 例えば、タイマーで加算した変数の値がバツマクグラウンドスレッド側で見えないなど。
    >
    > 現実には.NETの場合、あまりこういうことは起こりにくい実装にはなっていますが、正しい方法を知っておくに越したことはありません。
    > たとえば今の実装では、おそらくバックグラウンドワーカーへのアクセスでメモリ同期が働いてうまく動作します。
    > が、ある意味たまたまのようなもので、それに依存するのは望ましくはありません。
    > ※その前にSleepがきいてると思いますが、これはなくなったりする想定で

    必要に応じて排他をかけたり、シェイクハンドするかとは思いますが、
    今回はそれ以前の問題でした。どうもありがとうございます。
記事No.80073 のレス / END /過去ログ136より / 関連記事表示
削除チェック/

■80082  Re[2]: バックグランドワーカーとグローバル変数
□投稿者/ なちゃ -(2016/06/08(Wed) 22:14:51)
    因みにバックグラウンドワーカーへのアクセスでメモリ同期が発生するのは、キャンセル通知は当然最新値を確実に取得する必要があるので、それを保証する実装になっているからですが、多分その実装はバックグラウンドワーカーがMarshalByRefObjectの派生クラスであることに依存する(というか利用する)仕組みになってた気がします。

    何言ってるのかわからないマニアックな話ですね。
記事No.80073 のレス /過去ログ136より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -