4

私は2つのリストボックスを持っています。1つはマスター、もう1つは子です。マスターのインデックスが変更されると、子リストボックスにはマスターに関連するレコードが適切に入力されます。私の問題は、1つのマスターがすべてのレコードを取得するのに長い時間がかかり、レコードの取得が完了する前に、ユーザーが別のマスターをクリックして、入力にかかる時間が短い場合に発生します。最終的には、ユーザーがそのマスターを使用していなくても、時間がかかっていたマスターが子リストボックスに入力されます。

私はBackgroundWorkerスレッドを使用して入力を行ってきました。

bw_LoadAll.DoWork += new DoWorkEventHandler(bg_LoadAllWork);
bw_LoadAll.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_LoadAllWorkCompleted);
bw_LoadAll.WorkerSupportsCancellation = true;

マスターのSelectedIndexChangedイベントをサブスクライブし、キャンセルをtrueに設定しました。

bw_LoadAll.CancelAsync();

DoWorkメソッドのコードは次のとおりです。

List<object> s = Repository.Instance().LoadAll();
if (!bw_LoadAll.CancellationPending) {
    e.Result = s;
} else {
    e.Cancel = true;
}

しかし、何らかの理由で、完了したワーカーのコードが呼び出され続けます。ワーカーが完成したコードは次のとおりです。

if (!e.Cancelled) {
    ddl.DataSource = e.Result;
    ddl.DisplayMember = "QuickName";
    ddl.ValueMember = "ID";
}

このスレッドが戻るのをキャンセルするために他に何かしなければならないことはありますか?

4

3 に答える 3

5

メソッドbg_LoadAllWorkは、次のように定義する必要があります。

void bg_LoadAllWork(object sender, DoWorkEventArgs e)
{
    // Do your work here...
} 

bg_LoadAllWork内で、をチェックする必要がありe.CancellationPending、それがtrueの場合は、e.Cancel = true;

この最後の部分は重要です。e.Cancelを設定したことがない場合、「e.Cancelled」がtrueになることはありません。CancelAsyncの呼び出しは、実際には何もキャンセルしません。これは、「バックグラウンド作業がそれ自体をキャンセルするように要求する」のようなものです。キャンセルを引き起こすには、ロジックを配置する必要があります。

于 2009-06-18T16:59:50.713 に答える
0

do_work関数のCodeProjectから、ワーカースレッドでCancellationPendingを確認してから、DoWorkEventArgs.Cancel変数をtrueに設定する必要があります。

于 2009-06-18T16:54:50.920 に答える
0

私がBackgroundWorkerを使用してからしばらく経ちましたが、メモリが機能する場合、を呼び出すと、 LoadAllWorkがチェックしない限りbw_LoadAll.CancelAsync、メソッドが実際に中止されることはありません。LoadAllWorkbw_LoadAll.CancelationPending

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.cancelasync.aspxによって確認されました:"CancelAsyncは、保留中のバックグラウンド操作を終了する要求を送信し、CancellationPendingプロパティをtrueに設定します。

CancelAsyncを呼び出すと、workerメソッドはその実行を停止して終了する機会があります。ワーカーコードは、CancellationPendingプロパティを定期的にチェックして、trueに設定されているかどうかを確認する必要があります。」

したがって、SelectedIndexChangedイベントハンドラーを呼び出すとbw_LoadAll.CancelAsync()、trueに設定bw_LoadAll.CancelationPendingされますが、実際にはLoadAllWorkメソッドを中止しません。スローローダーはまだ終了します。

于 2009-06-18T16:58:28.577 に答える