0

TCP を定期的に送信するダイアログ ベースのプログラムを実行していますが、UDP メッセージもリッスンし、内容を GUI に表示します。最初に使用した単純な例では、while(true) でリッスンを開始すると、他のすべての GUI 機能がシャットダウンされました。次に、リッスンを行うためにスレッドを生成しようとしましたが、これらの例では、ビューから GUI 要素を非表示にする新しいクラスを作成する必要がありました。

私の質問は、UDP メッセージをリッスンし、GUI スレッドをブロックせずにコンテンツを GUI に書き込むためのベスト プラクティスは何ですか?

4

1 に答える 1

1

ある種のバックグラウンド スレッドでリスニングを行うコードを用意する必要があります。それは非常に簡単です.クラスからバックグラウンドスレッドを文字列化する方法はたくさんあります.ThreadBackgroundWorkerTaskThreadPool.QueueUserWorkItem

その後、必要なのは、UI を更新する方法だけです。これを行うにはいくつかの方法があります (使用している UI 機能 (WPF、winform など) に固有のものとそうでないものがあります)。

特に特定の UI テクノロジに依存しないため、使用IProgress<T>は特に便利です。UI でオブジェクトを作成しProgress、特定の結果が得られたときに UI を更新する方法を指定し、オブジェクトをバックグラウンド ワーカーに渡し、Report情報を受け取ったときにオブジェクトを進行させます。

例は次のようになります。

private void Form1_Load(object sender, EventArgs e)
{
    Progress<string> progress = new Progress<string>();
    progress.ProgressChanged += data =>
    {
        textBox1.AppendText(data);
    };

    Thread tcpListener = new Thread(() => ListenForData(progress));
    tcpListener.Start();
}

private void ListenForData(IProgress<string> progress)
{
    while (true)
    {
        Thread.Sleep(1000);//placeholder for real IO to get data
        progress.Report("data");
    }
}

C# 4.5 がない場合、独自のProgressクラスを作成するのは非常に簡単です。

public interface IProgress<T>
{
    void Report(T data);
}

public class Progress<T> : IProgress<T>
{
    SynchronizationContext context;
    public Progress()
    {
        context = SynchronizationContext.Current
            ?? new SynchronizationContext();
    }

    public Progress(Action<T> action)
        : this()
    {
        ProgressReported += action;
    }

    public event Action<T> ProgressReported;

    void IProgress<T>.Report(T data)
    {
        var action = ProgressReported;
        if (action != null)
        {
            context.Post(arg => action((T)arg), data);
        }
    }
}
于 2013-03-14T14:41:27.003 に答える