简体   繁体   English

如何在一段时间后取消异步任务

[英]How to cancel async Task after a period of time

In my Windows Store app I have a method 在我的Windows应用商店应用中,我有一个方法

public async static Task InitAds()
{
    Debug.WriteLine("API: Loading Ad images");
    await Task.WhenAll(ads.Select(l => l.Value).Where(l=>l!=null).Select(l => l.StartRotation()));
 }

I use to download and initialize (download, parse| Ads in a project. This method is awaited when called 我用来下载和初始化(下载,解析|项目中的广告。调用此方法时等待

...
await AdReader.InitAds()
...

The problem is that Ads server sometimes responds very slowly. 问题是广告服务器有时响应非常慢。 I want to have a timeout, say 10 seconds for this method to run. 我希望有一个超时,比如这个方法运行10秒。 If it does not finish in this timeout, I want it to be killed and my code to continue. 如果它没有在此超时完成,我希望它被杀死,我的代码继续。

What is the best way to implement this? 实现这个的最佳方法是什么? I found How to cancel a Task in await? 我找到了如何在等待中取消任务? but it uses a TaskFactory and when I try that approach and call my method in Task.Run it is not awaited and the code continues. 但它使用TaskFactory,当我尝试这种方法并在Task.Run中调用我的方法时,它不会等待,代码会继续。

Edit: 编辑:

The StartRotation is also an async method calling another async methods StartRotation也是一个异步方法,调用另一个异步方法

public async Task StartRotation(CancellationToken ct)
{
        if (Images.Count == 1)
        {
            await Image.LoadAndSaveImage(ct);
        }

        if (Images.Count <2) return;

        foreach (var img in Images)
        {
            await img.LoadAndSaveImage(ct);
        }

        Delay = Image.Delay;
        DispatcherTimer dt = new DispatcherTimer();
        dt.Interval = TimeSpan.FromMilliseconds(Delay);
        dt.Tick += (s, e) =>
        {
            ++index;
            if (index > Images.Count - 1)
            {
                index = 0;
            }
            Image = Images[index];
        };
        dt.Start();
    }

Cancellation is cooperative. 取消是合作的。 You just need to pass CancellationToken into your StartRotation : 您只需将CancellationToken传递到StartRotation

public async static Task InitAds(CancellationToken token)
{
  Debug.WriteLine("API: Loading Ad images");
  await Task.WhenAll(ads.Select(l => l.Value).Where(l=>l!=null).Select(l => l.StartRotation(token)));
}

And then call it as such: 然后将其称为:

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
await InitAds(cts.Token);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM