2

ソースがない .dll に埋もれているクラスに時間のかかるメソッドがあります。このメソッドを呼び出すときに UI をブロックしたくありません。これを行うために BackgroundWorker を使用しようとしています。btn_Click イベント ハンドラーから RunWorkerAsync を呼び出します。ワーカー スレッドの外部で dllClass インスタンスを作成すると (以下のように)、操作が完了するまで UI がフリーズします。この操作はまた、タイマーがカチカチ音をたてないようにブロックします。

public static dllClass dllClassInstance = new dllClass();

void worker1_DoWork(object sender, DoWorkEventArgs e)
{
    dllClassInstance.TimeConsumingMethod();
}

一方、(次のコード セグメントのように) ワーカー スレッド内でクラスをインスタンス化すると、意図したとおりに動作します。

void worker1_DoWork(object sender, DoWorkEventArgs e)
{
    dllClass dllClassInstance = new dllClass();

    dllClassInstance.TimeConsumingMethod();
}

後者を使用する際の問題は、時間のかかるメソッドの前後に他のメソッドを呼び出す必要があるため、その特定のワーカーの外部にあるクラス インスタンスにアクセスする必要があることです。また、e.Argument を介してクラス インスタンスを BackgroundWorker に渡そうとしましたが、UI がフリーズしました。UIをブロックせずにそのメソッドを呼び出す方法を提案している人はいますか?

4

4 に答える 4

3

UIをブロックせずにそのメソッドを呼び出す方法を提案している人はいますか?

内で何が起こっているかを知らなければdllClass、判断することはできません。

通常、どちらのコードでも UI がフリーズすることはありません。コンストラクター内でdllClass現在をキャプチャし、内部で使用しているため、ブロックが発生していると思われます。この場合、DoWork ハンドラー内でクラスを構築する可能性がありますが、代わりにクラスにスコープを設定すると、うまくいく可能性があります。ただし、同期コンテキストをキャプチャしている場合、クラスはスレッド アフィニティを持ち、UI スレッドで実行されることを期待している可能性があります。SynchronizationContextTimeConsumingMethod

次のように、ハンドラ内でインスタンスを構築してみることができます。

public dllClass dllClassInstance;

void worker1_DoWork(object sender, DoWorkEventArgs e)
{
    dllClassInstance = new dllClass(); // Construct here
    dllClassInstance.TimeConsumingMethod();
}

これはうまくいくかもしれませんが、私が言ったように、他の副作用があるかもしれません. dllClassUI スレッドで実行する必要があるスレッド アフィニティ ルールがないことを確認します。

于 2012-06-12T18:35:12.103 に答える
1

それはおそらくあなたのせいですdllClass。誰かがインスタンスのすべての呼び出しが同じスレッドで処理されることを確認したい場合を除いて、あなたが見ていることは起こらないはずです. dllClassコンストラクターでディスパッチャーを受け取り、そのディスパッチャーを介しTimeConsumingMethodて実際の処理を呼び出すと、フリーズした UI が表示されます。

于 2012-06-12T18:35:57.310 に答える
0

Reed が指摘したように、そのクラスの内部が何であるかを知らずに実際に解決するのは難しいかもしれません。ただし、ロード/準備、セットアップが必要な他のものがある場合は、バックグラウンドワーカークラス "ReportsProgress" = true を設定し、開始時に、ex に基づいて他の設定を取得および/または準備するメソッドをすぐに呼び出します。 : 進行状況が 1 (開始) の場合は、長いプロセスの他の要素を実行し、99 (終了) などの値で進行状況を報告し、そこからクリーンアップを行います。

これは役に立ちそうですか?すべてを 1 つのバックグラウンド ワーカー クラスにカプセル化することもできます。

于 2012-06-12T18:40:58.053 に答える
0

私は VB.net アプリケーションに取り組んでおり、Agilent デバイスと通信するための Visa Com 3.0 ドライバーで同じ問題に遭遇しました。これが私がそれを解決した方法です:

Dim task = New Threading.Tasks.Task(Of dllClass)(Function()
                                                     Return New dllClass()
                                                 End Function)
task.Start()
task.Wait()

public static dllClass dllClassInstance = task.Result;

void worker1_DoWork(object sender, DoWorkEventArgs e)
{
    dllClassInstance.TimeConsumingMethod();
}

基本的に、新しいスレッドで dllClass インスタンスを作成しますが、すぐにそのスレッドを破棄して参照を保持します。

于 2013-06-26T17:24:01.533 に答える