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

你可以使用一个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 回答
1

如果您不能使用 .NET 4.5(正如我在评论中提到的),那么您可以使用布尔值来取消循环。在这里,我修改了您的第二个选项:

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 回答