如何在执行下一个代码之前等待线程完成?

时间:2019-08-05 08:35:47

标签: c# async-await

我需要这样的代码:

module.StopAndWait();
module.DoSmth();
module.Resume();

我已经编写了AsyncModel类。行“ while(!isStopped);”有问题。在这一行,程序冻结。我认为必须更改isStopped,但不必更改。 我试图将isStopped声明为volatile。 但是无论如何程序在“ while(!isStopped);”上有问题。

public class AsyncModel
{
    bool run = false;
    bool isStopped;
    public async void Run()
    {
        if (run) return;
        await Task.Run(() => progr());
    }
    public void StopAndWait()
    {
        run = false;
        while (!isStopped) ;// <-- Problem
    }
    void progr()
    {
        isStopped = false;
        run = true;

        while (run)
        {
            Thread.Sleep(1500);
        }

        isStopped = true;
    }
}

2 个答案:

答案 0 :(得分:2)

我认为这段代码正在尝试运行一个可以在后台取消的循环。 最简单的方法是使用CancellationTokenSource和CancellationToken,例如:

void progr(CancellationToken token)
{
    while(!token.IsCancellationRequested)
    {
        // Do something expensive
    }
}

请注意,progr没有引用外部字段。它只需要token

应在任务本身开始之前创建CancellationTokenSource。

Task thatTask;
CancellationTokenSource cts;

public void StartTheJob()
{
    cts=new CancellationTokenSource();
    thatTask=Task.Run(()=>progr(cts.Token));
}

要停止任务,只需调用cts.Cancel()

public async Task StopTheJob()
{
    cts.Cancel();
    //Wait for the cancelled task to exit
    await thatTask;
}

要添加延迟,请使用await Task.Delay(...)而不是`Thread.Sleep()。 Task.Delay可以被取消并且不会阻塞用于运行任务的线程池线程:

async Task progr(CancellationToken token)
{
    while(!token.IsCancellationRequested)
    {
        // Do something expensive
        await Task.Delay(1000,token);
    }
}

检查Async in 4.5: Enabling Progress and Cancellation in Async APIs了解更多

答案 1 :(得分:0)

看来,使用普通的旧同步代码可以轻松解决您的问题。另外,尝试使用Task.Delay()代替Thread.Sleep。最后,方法命名的一致性。