如何在类构造函数/计时器回调中等待任务

时间:2014-09-12 20:08:01

标签: c# .net asynchronous task-parallel-library async-await

我有一个异步函数(不会返回实际值,只返回Task对象),我需要在类构造函数中运行,以及当Threading.Timers.Timer触发时。

我无法将构造函数sub标记为async,当我使用AddressOf设置计时器回调时,它会警告我"从此异步函数返回的任务将被删除,并且忽略其中的任何异常。考虑将其更改为Async Sub,以便传播其异常。"。我听说使用Async subs / void不是一个好主意,如果可能的话应该避免使用。

构造函数代码

Public Sub New(File As String)
  Me.New()
  Await ImportXml(File)
End Sub

定时器代码

Private WithEvents SaveTimer As New Threading.Timer(AddressOf Save, Nothing, 30 * 1000, Threading.Timeout.Infinite)

我认为使用构造函数我可以将文件的加载分成单独的子文件(除非有更好的方法),但不知道如何处理计时器。我想知道我是否做错了,并且有办法安排任务,某种任务计时器?

2 个答案:

答案 0 :(得分:5)

由于构造函数无法返回任务,您可以改为使类型隐藏其构造函数并公开 异步的一个或多个工厂方法,并返回该类型的用户可用于创建实例的任务: / p>

public class Foo
{
    private Foo()
    {
    }

    public static async Task<Foo> CreateAsync()
    {
        Foo foo = new Foo();
        await foo.InitializeAsync();
        return foo;
    }
}

对于计时器,你可以简单地避免使用实际的计时器,只需创建一个async方法:

public static async Task DoStuff()
{
    while (true)
    {
        await Task.Run(() => SomeWork());
        await Task.Delay(TimeSpan.FromSeconds(30));
    }
}

答案 1 :(得分:1)

你不能await构造函数中的任务(这是正确的,因为你不能从构造函数返回任务)。但是,您可以在构造函数中启动任务,将其作为属性存储在类中,并在实际需要时将其存储为await

public class Hamster
{
    public Task Creation { get; private set; }
    public Hamster()
    {
        Creation = CreateAsync();
    }
}

var hamster = new Hamster();
await hamster.Creation;
  

...并且有一种方法来安排任务,某种任务计时器

是的,有。您可以启动任务,并使用Task.Delay

异步等待
async Task DoSomethingAsync(CancellationToken cancellationToken)
{
    await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken);
    DoSomething();
}