0

で長いタスクを実行しておりBackgroundWorker、 を介して UI を更新していReportProgressます。ただし、プロセスの途中で、データを取得するために COM 呼び出しを行う必要があり、UI スレッドで行う必要があると思います。Control.Invoke を介してこれを実行してみました。しかし、私はデッドロックを取得しています。(with )Control.Invokeで使用できませんか?BackgroundWorkerShowDialog

コードを単純化しようとしました:

        var log = new LogWindowForm();
        worker.DoWork += (sender, args) =>
        {
                creator.LogProgress = (s, i) => worker.ReportProgress(i,s);
                creator.GetMoreDataFunc = (s) => InvokeGetMoreDataOnGuiThread(log, s);
                ...
                var data = GetMoreDataFunc("id:"+id)
        };
        worker.RunWorkerAsync();
        log.ShowDialog();


    private Dictionary<string, string> InvokeGetMoreDataOnGuiThread(Control invokeControl, string id)
    {
        var data = new Dictionary<string, string>();
        Action action = () => data = GetMoreDataFromComObject(mainComObject, id);
        invokeControl.Invoke(action); // deadlock!
        return data;
    }

編集:

例外はありません。UI は更新され続けますが、進行が停止します。Break All は、Control.Invoke 呼び出しでワーカー スレッドを表示し、ShowDialog 呼び出しで GUI スレッドを表示します。

GUI スレッドがメッセージ ループにあるようです。

System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext コンテキスト) + 0x65 バイト

それがUIが更新され続ける理由だと思います。BackgroundWorker 内にロックはありますか?

4

1 に答える 1

0

COMオブジェクトが何をするか、または何を必要とするかがわからないので、推測します:

COM オブジェクトが UI htread を必要とする理由は、(ほとんどの場合) UI スレッドが STA スレッドとしてマークされているためです。

COM オブジェクトにシングル スレッド アパートメントが必要な場合は、STA スレッドとしてマークされた非 UI スレッドを使用できます。そうすれば、UI スレッドを要求しなくなります。

参照: STA と MTA について説明していただけますか?

および: .NET での STA の説明

および.NET スレッド STA または MTA を作成する方法、または属性を使用する方法

于 2013-01-23T10:28:48.220 に答える