-1

最近Threads、アプリケーション内でAutoResetEvent. コンソール アプリでは、ループを作成し、スレッドがデータを処理する準備ができていることを示す信号を待機することにwhile(true)依存します。ワーカー スレッド用のメソッドと、ワーカー スレッドとメイン スレッド間で共有するデータ要素を持つを使用して、スレッド間でデータを共有する方法を知っています。AutoResetEvent.WaitOne()AutoResetEvent.Set()Class

私の質問はAutoResetEvent、通常はコマンド ループが表示されない Winforms アプリで使用する方法です。WaitOne()Winforms アプリのどこに呼び出しを配置すればよいですか?

サンプル コードについて: 最良の例は、タイムアウトを使用して を作成する方法に関するこのサイトの回答Console.ReadLine()です。これは基本的に の使用方法の簡単な例signalsです。その例は、コンソール アプリの例です。

グーグルで検索すると、私の質問に対する答えはBackgroundWorkerコントロールを使用している可能性がありますか?

4

3 に答える 3

1

あなたの質問から、UI スレッドはイベントを待つ必要があることを理解しています。

WinForms アプリケーションの UI スレッドは、オペレーティング システムに制御を渡してユーザーの操作を可能にする必要があるため、 を待機することAutoResetEventは適切ではありません。UI スレッドと通信する場合は、次を使用できます。

bool ret = (bool)myFormInstance.Invoke(
    new Func<DataClass, bool>(myFormInstance.DoStuff), 
    myData);

public class MyForm : Form
{
    public bool DoStuff(DataClass data)
    {
        ....
    }
}

BeginInvokeを使用して、UI スレッドでコードを非同期的に実行することもできます。

逆の方法が必要な場合 (UI スレッドがワーカー スレッドに処理を開始するように指示する場合) を使用できますBackgroundWorker。それに関するチュートリアルがたくさんあるはずです。

于 2015-03-11T15:45:17.697 に答える
1

Winforms でマルチスレッドを使用するための完全な解決策は、 と を組み合わせることBackgroundWorkerですAutoResetEvent

私が正しければ、それBackgroundWorkerは のようなもので、バックグラウンド スレッドから UI へのシグナル伝達のためThreadにイベント ハンドラーと適切に連携するという利点があります。UI からバックグラウンド スレッドへのシグナリングProgressChangedが必要な場合があります。AutoResetEvent私の場合、[次へ] ボタンを使用して、データを受信するための新しいブロッキング呼び出しを開始したいと考えています。以下は、私がテストしたコードです。

ただし、問題は、ここで使用するよりも良い方法が本当にないかどうかAutoResetEventです。しかし、うまくいくようです。

/// <summary>
/// The Next button uses this to signal the BackgroundWorker
/// to start the blocking call to Receive data
/// </summary>
private AutoResetEvent _SignalStartReceive  = new AutoResetEvent(false);

/// <summary>
/// To implement variable time it takes until Receive returns
/// </summary>
private Random _RandomTime = new Random();

// Class Initializer
public Form()
{
    backgroundWorker_Receive.WorkerReportsProgress = true;
    backgroundWorker_Receive.RunWorkerAsync();
    return;
}

/// <summary>
/// User presses this button when he is ready to Receive the next
/// data packet
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button_ReceiveNext_Click(object sender, EventArgs e)
{
    checkBox_Receive.Checked = true;
    textBox_ReceivedContent.Text = "";
    _SignalStartReceive.Set();
    return;
}

/// <summary>
/// User presses this button when he is ready to Receive the next
/// data packet
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button_ReceiveNext_Click(object sender, EventArgs e)
{
    checkBox_Receive.Checked = true;
    textBox_ReceivedContent.Text = "";
    _SignalStartReceive.Set();
    return;
}

/// <summary>
/// This is the worker thread, running in the background
/// while the UI stays responsive
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker_Receive_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    while (true)
    {
        // blocking: wait for button click
        _SignalStartReceive.WaitOne();
        // blocking: wait for datagram over network
#if true //temporary code to simulate UdpClient.Receive()
        DateTime StartTime = DateTime.Now;
        int RandomTimeMs = 2000 + 30 * _RandomTime.Next(100);
        Thread.Sleep(RandomTimeMs);
        _ReceivedDatagram = string.Format("UDP data ... {0} ms", (DateTime.Now - StartTime).TotalMilliseconds);
#else
        something with UdpClient.Receive();
#endif
        // succeeded:
        worker.ReportProgress(0);//fire the event: Receive_ProgressChanged (argument does not matter)
    }
    //return; //unreachable, but would fire the Completed event
}

/// <summary>
/// Handler for the ReportProgress() call by the BackgroundWorker Thread
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker_Receive_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    textBox_ReceivedContent.Text = _ReceivedDatagram;
    checkBox_Receive.Checked = false;
    return;
}
于 2015-03-12T16:39:48.693 に答える
1

はい、BackgroundWorker代わりに使用します。

于 2015-03-11T15:47:03.593 に答える