5

次のコードには、メインスレッドがウェイトハンドルをリセットした後、ワーカースレッドがすぐに終了したり、最終アクションを実行したりしないという欠点があります。代わりに、ループの次の反復に到達するまで実行を継続し、その時点で無期限にブロックされます。

static void Main()
{
 ManualResetEvent m = new ManualResetEvent(true); // or bool b = true
 Thread thread = new Thread(new ThreadStart(delegate()
 {
    while(m.WaitOne()) //or while(b)
    {
        //do something
    }
    //perform final operation and exit
 }));

 thread.Start();

 //do something

 m.Reset(); //or b = false

 //do something else
 }

次のコードには、Abort()メソッドを使用するという欠点がありますが(絶対に避けるべきだと言う人がいます)、私が探していることを正確に実行します。メインスレッドがそうするように指示したらすぐに、最後の操作を実行して終了します。

static void Main()
{
 Thread thread = new Thread(new ThreadStart(delegate()
 {
    try
    {
        while(true)
        {
            //do something
        }
    }
    catch(ThreadAbortException e)
    {
           //perform final operation and exit
    }
 }));

 thread.Start();

 //do something

 thread.Abort();    

 //do something else
 }

どちらのソリューションも理想的ではないので、私が探している機能を実装するための適切な方法は何ですか?

(.net 4.5のタスクを含まないソリューションが望ましいです)

4

2 に答える 2

1

(コメントで述べたように).NET 4.5を使用できない場合は、ブール値を使用してループをキャンセルできます。ここで、2番目のオプションを変更しました。

static void Main()
{
    volatile bool keepGoing = true;

    Thread thread = new Thread(new ThreadStart(delegate()
    {
        while(keepGoing)
        {
            //do something
        }

        //logic to perform when the thread is cancelled
    }));

    thread.Start();

    //do something

    keepGoing = false; 

    //do something else
 }

bool値をvolatileとしてマークすると、チェックするときに常に正しい値を使用できるようになります。このアプローチにより、ループ内で実行していたアクションがすべて完了し、「ダーティ」状態のままにならないようにすることもできます。

http://msdn.microsoft.com/en-us/library/x13ttww7%28VS.80%29.aspx

于 2013-01-25T18:38:55.183 に答える
1

あなたは使用することができますBackgroundWorker

static void Main()
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += worker_DoWork;
    worker.RunWorkerAsync();

    // do something 

    worker.CancelAsync();

    // do something else
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    while(!worker.CancellationPending)
    {
        // do something
    }
    // perform final action
}

(コードはテストされていません)

于 2013-01-25T18:42:05.387 に答える