异步方法错误帮助我

时间:2017-10-02 06:36:22

标签: c# asynchronous

这是Simple Daily Trigger类,我从某个控制器调用此函数 - >(" DailyTrigger(int hour,int minute,int second = 0)")。 下次第一次使用(使用Task.delay)时出现错误

public class DailyTrigger
{
    readonly TimeSpan triggerHour;

    public DailyTrigger(int hour, int minute , int second = 0)
    {
        triggerHour = new TimeSpan(hour, minute, second);
        InitiateAsync();
    }

    async void InitiateAsync()
    {
        while (true)
        {
            var triggerTime = DateTime.Today + triggerHour - DateTime.Now;
            if (triggerTime < TimeSpan.Zero)
                triggerTime = triggerTime.Add(new TimeSpan(0,2,0));
            await Task.Delay(triggerTime);
            OnTimeTriggered?.Invoke();

        }
    }

从控制器中调用

var trigger = new DailyTrigger(13,01);
                trigger.OnTimeTriggered += () =>
                {
                    var res = AanModel.GetById<Company_Priority>(prio_obj.id);
                    res.version = "5";
                    res.Create();
                };

该错误

  

&#34;异步模块或处理程序在异步时完成   操作仍在等待&#34;

1 个答案:

答案 0 :(得分:3)

这是异步编程的一个众所周知的问题。您最好通过 jonpreece 阅读Quick tip: Avoid ‘async void’等文章,了解其工作原理。

错误:

  

异步模块或处理程序在异步时完成   手术还在等待。

说明

  是的,你有竞争条件。在它之前返回的方法   完成执行。在引擎盖下,框架没有创建   该方法的任务因为该方法不返回任务。   因此,在调用FirstOrDefaultAsync时,该方法不会暂停   执行并遇到错误。

解决方案:

  

要解决此问题,只需更改方法的返回类型即可   从void到Task。别担心,你实际上不必返回   任何事情,如果编译器知道不生成构建错误   没有退货声明。一个简单的解决方案,当你知道什么   问题是!

更新:

如果您仍想继续在构造函数中调用异步方法,那么最好通过 Stephen Cleary 阅读Async OOP 2: Constructors

  

异步构造带来了一个有趣的问题。这将是   能够在构造函数中使用await是有用的,但这意味着   构造函数必须返回一个表示一个的Task   将来构建的价值,而不是构造的价值   值。这种概念很难融入其中   现有语言。

     

底线是不允许异步构造函数,所以让我们   探索一些替代方案。

如果你阅读得足够远,你会看到......

什么不该做

public sealed class MyClass
{
  private MyData asyncData;
  public MyClass()
  {
    InitializeAsync();
  }

  // BAD CODE!!
  private async void InitializeAsync()
  {
    asyncData = await GetDataAsync();
  }
}

更好地检查它,这是一个非常有趣的阅读。