告诉线程正在执行循环以跳出循环并执行其他操作的正确方法是什么?

时间:2021-11-21 14:30:23

The following code has the disadvantage that the worker thread will neither terminate immediately nor perform a final action after the main thread resets the waithandle. Instead, it will continue doing what it is doing until it reaches the next iteration of the loop, at which point it will be blocked indefinitely.

以下代码的缺点是,在主线程重置waithandle之后,工作线程不会立即终止,也不会执行最终操作。相反,它将继续做它正在做的事情,直到它到达循环的下一个迭代,此时它将被无限期地阻塞。

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
 }

The following code has the disadvantage that it uses the Abort() method (there are people who say it should be avoided at all costs), but accomplishes exactly what I'm looking for: force the worker thread to break out of the loop as soon as the main thread tells it to do so, perform a final operation, and exit.

下面的代码有缺点,它使用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
 }

Since neither solution is ideal, what's the proper way to implement the functionality I'm looking for?

既然两种解决方案都不是理想的,那么实现我正在寻找的功能的正确方法是什么呢?

(I'd prefer a solution that doesn't involve .net 4.5's tasks)

(我更喜欢不涉及。net 4.5任务的解决方案)

2 个解决方案

#1


1  

You can use a 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
}

(Code is untested)

(未经测试的代码)

#2


1  

If you cannot use .NET 4.5 (as I mentioned in a comment) then you could use a boolean value to cancel the looping. Here, I modified your second option:

如果不能使用。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
 }

Marking the bool value as volatile will ensure that you always have the correct value when checking it. This approach also ensures whatever action you were performing inside the loop is completed and not left in a "dirty" state.

将bool值标记为volatile将确保在检查时始终具有正确的值。这种方法还确保您在循环中执行的任何操作都已完成,不会处于“脏”状态。

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

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

#1


1  

You can use a 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
}

(Code is untested)

(未经测试的代码)

#2


1  

If you cannot use .NET 4.5 (as I mentioned in a comment) then you could use a boolean value to cancel the looping. Here, I modified your second option:

如果不能使用。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
 }

Marking the bool value as volatile will ensure that you always have the correct value when checking it. This approach also ensures whatever action you were performing inside the loop is completed and not left in a "dirty" state.

将bool值标记为volatile将确保在检查时始终具有正确的值。这种方法还确保您在循环中执行的任何操作都已完成,不会处于“脏”状态。

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

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