.net 我对Task.Run(async()=>await SomeMethodAsync())和Task.Run(()=>SomeMethodAsync)感到困惑

xzv2uavs  于 2023-08-08  发布在  .NET
关注(0)|答案(3)|浏览(140)

对我来说,理解下面的异步用法有点困难。我在本地测试过,发现两者的实际结果是一样的,但不知道两者应该在哪些场景下使用,是否存在潜在问题?
最基本的要求是有一个属性可以做一些事情。如果为true,它将启动一个线程(不干扰当前线程)执行循环操作,如果为false,它将关闭循环操作。

public bool IsMaster
{
    get { return _isMaster; }
    set
        {
           _isMaster = value;

           if (_isMaster)
           {
              if (_httpTask == null || _httpTask.IsCompleted || _httpTask.IsFaulted)
              {
                 _httpTask = Task.Run(async () => await HandleHesApiRequest());
                 Logobject.LogDebug($"[HttpService]Master core,HTTP listenning started");
              }
           }
           else
           {
              while (true)
              {
                  //dispose resource
                 if (_httpTask == null || _httpTask.IsCompleted || _httpTask.IsFaulted)
                 {
                      Stop();
                      Logobject.LogDebug($"[HttpService]Worker core,HTTP listenning stopped");
                      break;
                  }

                 Thread.Sleep(2000);
               }
           }
       }
}

字符串
异步方法是这样的

public async Task HandleHesApiRequest()
{
    int relayCount = 2;

    while (true)
    {
        if (!IsMaster)
        {
           Logobject.LogDebug($"[HttpService]Changed to worker core,HTTP listenning stopping...");
           break;
        }
        else
        {
            //Do some job whether 'IsMaster==true'
        }

       await Task.Delay(xx)
     }

   Logobject.LogDebug($"[HttpService]Exit service...");

   await Task.CompletedTask;
}


问题是我不明白

_httpTask =Task.Run(()=>HandleHesApiRequest());


和/或

_httpTask = Task.Run(async () => await HandleHesApiRequest());


SDK是.Net Core 3.1

hof1towb

hof1towb1#

如前所述,it is justifiable在本例中省略了委托上的async,因为它没有做任何有用的事情。
然而,无论如何,你不应该在setter中运行如此复杂的东西,当然你也不应该仅仅因为它是一个setter就阻止循环等待任务。相反,创建一个单独的Set方法,即asyncawait任务。这还允许任务上的异常正确地冒泡。
另外,你的if逻辑好像不对,取消的时候好像应该反过来。IsCompleted包括IsFaulted

public bool IsMaster { get; private set; }

public async Task SetIsMaster(bool value)
{
    _isMaster = value;

    if (_httpTask?.IsCompleted ?? false)
    {
        await _httpTask;  // bubble up exceptions
        _httpTask = null;
    }

    if (_isMaster)
    {
        if (_httpTask == null)
        {
            _httpTask = Task.Run(HandleHesApiRequest);
            Logobject.LogDebug($"[HttpService]Master core,HTTP listenning started");
        }
    }
    else
    {
        // original logic seems incorrect
        if (_httpTask != null)
        {
            Stop();
            await _httpTask;
            _httpTask = null;
            Logobject.LogDebug($"[HttpService]Worker core,HTTP listenning stopped");
        }
    }
}

字符串

rvpgvaaj

rvpgvaaj2#

对于给定的例子,没有真实的的区别。对于一个只调用另一个方法的方法来说,是否等待返回的任务应该没有什么实际的区别。
不过,你最好用个计时器。“循环睡眠”是一个反模式,而“循环任务.延迟”稍微好一点,它可能仍然不是最好的方法。
一些基本的经验法则是:
1.如果您正在执行IO操作,例如从磁盘阅读或发出http请求,请使用Async模式。
1.如果你正在进行大量的计算,请使用后台线程,即第一个月
1.如果你定期做任何事情,你应该使用timer
在某些情况下,您可能希望合并模式,例如使用异步模式来等待缓慢的计算,或者将periodic timer与异步代码一起使用。但这实际上取决于具体情况,示例中没有足够的细节来提供任何具体的建议。
我也会推荐阅读关于这个主题的很多内容。多线程和async/await都是相当复杂的主题。Dissecting the async methods in C#There Is No Thread是一些不错的读物,但还有很多其他不错的资源。

rbpvctlc

rbpvctlc3#

  • _httpTask =Task.Run(()=>HandleHesApiRequest());:它正在向Task.Run传递一个同步委托,这意味着Task.Run方法将返回一个Task,该Task表示HandleHesApiRequest的完成。
  • _httpTask = Task.Run(async () => await HandleHesApiRequest());:它传递一个异步委托给Task.Run,这意味着Task.Run方法将返回一个Task,该Task表示异步lambda的完成,而异步lambda的完成则等待HandleHesApiRequest的完成。
  • 唯一的区别是,在第一个中,你创建了另一个异步lambda函数来生成一个Task,而你的Get方法已经是Task了,所以你可以直接使用它。

相关问题