58

一連のデジタル IO アクションを繰り返し実行する Windows アプリケーションを作成しています。

この一連のアクションは、ユーザーが「START」ボタンをクリックすると開始され、backgroundWorker1_DoWork() のバックグラウンド ワーカーによって実行されます。

ただし、「このバックグラウンド ワーカーは現在ビジー状態です.......」というエラー メッセージが表示される場合があります。

別の一連のアクションを開始する前に、while ループを使用してバックグラウンド ワーカーを「強制終了」することにより、コードに以下を実装することを考えています。

if (backgroundWorker1.IsBusy == true)
{

    backgroundWorker1.CancelAsync();
    while (backgroundWorker1.IsBusy == true)
    {
        backgroundWorker1.CancelAsync();
    }

    backgroundWorker1.Dispose();

}

backgroundWorker1.RunWorkerAsync();

私の主な関心事は、最終的に backgroundWorker1 が「殺される」ことでしょうか? もしそうなら、それを完了するのに長い時間がかかりますか?

このコーディングは無限ループに陥りますか?

4

6 に答える 6

79

次のようなものを使用できます (マネージド スレッドの中止と ThreadAbortException の詳細については、Chris Sells による「 Rotor を使用した ThreadAbortException の深さの配管(Web アーカイブ)」を参照してください)。

public class AbortableBackgroundWorker : BackgroundWorker
{

    private Thread workerThread;

    protected override void OnDoWork(DoWorkEventArgs e)
    {
        workerThread = Thread.CurrentThread;
        try
        {
            base.OnDoWork(e);
        }
        catch (ThreadAbortException)
        {
            e.Cancel = true; //We must set Cancel property to true!
            Thread.ResetAbort(); //Prevents ThreadAbortException propagation
        }
    }

 
    public void Abort()
    {
        if (workerThread != null)
        {
            workerThread.Abort();
            workerThread = null;
        }
    }
}

使用法:

backgroundWorker1 = new AbortableBackgroundWorker();
//...
backgroundWorker1.RunWorkerAsync();

if (backgroundWorker1.IsBusy == true)
{
    backgroundWorker1.Abort();
    backgroundWorker1.Dispose();
}
于 2010-01-20T20:22:44.407 に答える
1

私は同じ問題を抱えていました。これが役立つかどうかはわかりませんが、バックグラウンドワーカーにループがあるか、終了すると思います。あなたがする必要があるのは、あなたのループを中に入れることです。

バックグラウンドワーカーの中に入れます:

while (backgroundworker1.CancellationPending == false)
{
    //Put your code in here
}

このバックグラウンド ワーカーを強制終了するには、次のボタンを配置できます。

BackgroundWorker1.CancelAsync()

これが役立つことを願っています。

于 2010-01-12T11:43:18.317 に答える
0

私は(私が思うに)仕事をするものをまとめました。私がオフになっている場合はお知らせください。これがどのように機能するかの簡単な例です。

var backgroundWorker = new BackgroundWorker(){WorkerSupportsCancellation = true};

backgroundWorker.DoWork += (sender, args) =>
         {                 
                 var thisWorker = sender as BackgroundWorker;
                 var _child = new Thread(() =>
                                               {
                                                   //..Do Some Code

                                               });
                 _child .Start();
                 while (_child.IsAlive)
                 {
                     if (thisWorker.CancellationPending)
                     {
                         _child.Abort();
                         args.Cancel = true;
                     }
                     Thread.SpinWait(1);
                 }                 
         };

 backgroundWorker.RunWorkerAsync(parameter);
 //..Do Something...
backgroundWorker.CancelAsync();

バックグラウンド ワーカーはスレッド プールの一部であるため、アボートしたくありません。しかし、アボートを発生させることができるスレッドを内部で実行することができます。その後、backgroundWorker は基本的に、子スレッドが完了するか、プロセスを強制終了するように通知するまで実行されます。その後、バックグラウンド ワーカー スレッドは読み取りプールに戻ることができます。通常、これをヘルパー クラスにラップし、バックグラウンド スレッドで実行するデリゲート メソッドをパラメーターとして渡し、それを子スレッドで実行します。

誰かが壁に頭をぶつけているかどうか教えてください..

于 2010-04-07T03:04:40.313 に答える
-1
public class abortableBackgroundworker: BackgroundWorker
{
    public bool Kill = false;

    protected override void OnDoWork(DoWorkEventArgs e)
    {


        var _child = new Thread(() =>
        {
            while (!Kill)
            {

            }
            e.Cancel = true;//..Do Some Code

        });
        _child.Start();
        base.OnDoWork(e);

    }



}

kill を true に設定してスレッドを強制終了し、アボートの問題はありません:)

于 2011-09-04T05:54:55.500 に答える