可以在ThreadStart方法中使用"async"吗?

Jam*_*mes 11 c# async-await

我有一个Windows服务使用Thread和SemaphoreSlim每60秒执行一些"工作".

class Daemon
{
    private SemaphoreSlim _semaphore;
    private Thread _thread;

    public void Stop()
    {
        _semaphore.Release();
        _thread.Join();
    }

    public void Start()
    {
        _semaphore = new SemaphoreSlim(0);
        _thread = new Thread(DoWork);
        _thread.Start();
    }

    private void DoWork()
    {
        while (true)
        {
            // Do some work here

            // Wait for 60 seconds, or exit if the Semaphore is released
            if (_semaphore.Wait(60 * 1000))                
            {
                return;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想从中调用异步方法DoWork.为了使用await我必须添加async到的关键字DoWork:

private async void DoWork()
Run Code Online (Sandbox Code Playgroud)
  1. 有什么理由不这样做吗?
  2. 如果DoWork已经在专用线程内运行,那么DoWork是否能够异步运行?

Mar*_*ell 7

可以做到这一点,但这不是一个好主意.一旦第一次await点击没有同步完成,其余的工作将在一个延续时完成,而不是你开始的线程(_thread); 你开始的线程将在第一个终止await.无法保证延续将返回到原始线程,并且在您的方案中,它不能 - 该线程现在是吐司.这意味着:

  1. _thread没有意义,也不代表行动的状态; 因此,你的Stop()方法与_thread.Join();你没有做你期望它做的事情
  2. 你创建了一个线程(分配线程很昂贵,特别是因为堆栈的大小)只是让它几乎立即退出

通过使用Task.Run启动此类操作可以避免这两个问题.

  • 这对于OP来说并不是一个好主意,但是是否有使用异步方法启动线程的最佳实践?“Thread”构造函数和“Task.Factory.StartNew”都没有接受“Func<Task>”的重载,并且“Task.Run”创建线程池线程。我应该这样做 `void Foo() => FooAsync().Wait(); async Task FooAsync() { ... }` 并使用 `Foo` 作为 `ThreadStart`? (3认同)
  • @Kamran,你总是可以现在创建委托,然后调用 Task.Run ...... (3认同)
  • @o4zloiroman,这只是 a) 手动线程和 b) 异步操作如何工作的直接结果;存在通过“Thread”(而不是池线程)启动的线程来调用传递给它的委托,然后终止;“async void”方法仅同步运行到第一个不完整的异步等待(“async Task”等也是如此,但对于“async Task”,不完整状态至少对调用者可见)。所以:当“async void”方法遇到不完整的等待时:您为其生成的线程:展开并死亡。当等待完成时:它将在其他地方发生。 (3认同)