3

私のアプリケーションでは、Bitmapオブジェクトを描画するスレッドを作成しました。描画が完了するform.Invoke(form.Refresh)と、メイン フォームにビットマップを描画するスレッドが呼び出されます。(form私のアプリケーションのメインフォームへの参照です。)

問題Invoke: 他のスレッドが UI スレッドからのコールバック メッセージを待機しているときに (呼び出しのために) フォームを閉じると、スレッドが無期限に (?) 待機し、本質的にスタックして、アプリケーションが妨げられることに気付きました。閉店から。

BeginInvokeスレッドの作業でフォームを更新するのにかかる時間を考慮する必要があるため、私のプログラムでは使用は意味がありません。

Q:これを防ぐ最善の方法は何ですか?

編集:私はいくつかの場所でそれは悪い考えだと読んだことがありますが、これに対処する唯一の方法はThread.Abort(). Invoke呼び出しでスタックしただけなので、フラグなどを使用してスレッドを閉じることはできません。

編集 2:明確にするために、私が探しているのは、Invokeコールバックの待機を停止して作業を続行する必要があることをワーカー スレッドに伝える方法です。

4

2 に答える 2

2

もちろん、最善の答えは BeginInvoke を使用することです。UI スレッドが結果を処理するまでスレッドを待機させる必要がある場合は、プロセスに別の同期メソッドを追加する必要があります。

AutoResetEvent は、次のようなゲートとして機能します。

using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

public class MainForm : Form
{
    protected override void OnLoad(EventArgs e)
    {
        new Thread(ProcessBitmap) { IsBackground = true }.Start(null);
        base.OnLoad(e);
    }

    void DoneProcessingBitmap(Bitmap bitmap)
    {
        Trace.WriteLine("Done Processing Bitmap");
        uiDoneEvent.Set();
    }

    AutoResetEvent uiDoneEvent = new AutoResetEvent(false);
    volatile bool terminate = false;

    void ProcessBitmap(object state)
    {
        while (!terminate)
        {
            Bitmap bitmap = (Bitmap)state;
            Trace.WriteLine("Processing Bitmap");
            Thread.Sleep(5000); // simulate processing
            BeginInvoke(new Action<Bitmap>(DoneProcessingBitmap), bitmap);
            Trace.WriteLine("Waiting");
            uiDoneEvent.WaitOne();
        }
    }

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }
}
于 2012-05-04T14:21:45.810 に答える
0

を呼び出す前に、フォームがまだ存在するかどうかを確認してくださいInvoke。何かのようなもの...

if (form != null && !form.Disposed)
    form.Invoke(form.Refresh());
于 2012-05-04T14:18:12.650 に答える