c # - Timeout for async opgave

Indlæg af Hanne Mølgaard Plasc

Problem



Min ansøgning udfører i øjeblikket Adobe Illustrator med nogle kommandoer. Venter, når resultatfilen vises i en eller anden nøjagtig mappe (med async-funktion) og gør noget med filen, når den er klar.


Men problemet er, at Adobe Illustrator undertiden fejler, og app holder op med at vente. I sådanne tilfælde kan jeg ikke finde ud af, hvordan kan jeg anvende timeout mekanisme til at dræbe Adobe Illustrator og springe over den nuværende proces.


Her er koden:


...
await WhenFileCreated(result\_file\_name);
if (File.Exists(result\_file\_name))
{
...


public static Task WhenFileCreated(string path)
{
    if (File.Exists(path))
        return Task.FromResult(true);

    var tcs = new TaskCompletionSource<bool>();
    FileSystemWatcher watcher = new FileSystemWatcher(Path.GetDirectoryName(path));

    FileSystemEventHandler createdHandler = null;
    RenamedEventHandler renamedHandler = null;
    createdHandler = (s, e) =>
    {
        if (e.Name == Path.GetFileName(path))
        {
            tcs.TrySetResult(true);
            watcher.Created -= createdHandler;
            watcher.Dispose();
        }
    };

    renamedHandler = (s, e) =>
    {
        if (e.Name == Path.GetFileName(path))
        {
            tcs.TrySetResult(true);
            watcher.Renamed -= renamedHandler;
            watcher.Dispose();
        }
    };

    watcher.Created += createdHandler;
    watcher.Renamed += renamedHandler;

    watcher.EnableRaisingEvents = true;

    return tcs.Task;
}


Hvordan ansøger jeg timeout til dette? Nogen forslag?

Bedste reference


Prøv at ændre din kode for at indstille denne timeout for eksempel.


var tcs = new TaskCompletionSource<TestResult>();

const int timeoutMs = 20000;
var ct = new CancellationTokenSource(timeoutMs);
ct.Token.Register(() => tcs.TrySetCanceled(), useSynchronizationContext: false);


Flere detaljer, du kan finde i:
Timeout en async metode implementeret med TaskCompletionSource

Andre referencer 1


Den enkleste måde ville være at køre en Task.Delay mod den aktuelle opgave:


await Task.WhenAny(WhenFileCreated(result\_file\_name), 
                   Task.Delay(TimeSpan.FromSeconds(5));


En bedre måde ville være at implementere annullering i din async-metode


public static Task WhenFileCreated(string path, 
                                   CancellationToken ct = 
                                       default(CancellationToken))
{
     //...
     var tcs = new TaskCompletionSource<bool>();
     ct.Register(() => tcs.TrySetCanceled())
     //...
}


... og derefter passere i en annulleringstoken med en timeout: [8]


using(var cts = new CancellationTokenSource(5000))
{
    try
    {
        await WhenFileCreated(string path, cts.Token);
    }
    catch(TaskCanceledException)
    {
        //...
    }
}