Тайм-аут для асинхронной задачи - PullRequest
0 голосов
/ 26 апреля 2018

Мое приложение в настоящее время выполняет Adobe Illustrator с некоторой командой. Ожидает, когда файл результатов появится в какой-то конкретной папке (с асинхронной функцией), и что-то делает с файлом, когда он будет готов.

Но проблема в том, что иногда Adobe Illustrator дает сбой, и приложение продолжает ждать. В таких случаях я не могу понять, как я могу применить механизм тайм-аута, чтобы убить Adobe Illustrator и пропустить текущий процесс.

Вот код:

...
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;
}

Как применить тайм-аут к этому? Есть предложения?

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Простейшим способом было бы состязаться с Task.Delay против фактической задачи:

await Task.WhenAny(WhenFileCreated(result_file_name), 
                   Task.Delay(TimeSpan.FromSeconds(5));

Лучшим способом было бы реализовать отмену в вашем асинхронном методе

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

... и затем передать токен отмены с таймаутом :

using(var cts = new CancellationTokenSource(5000))
{
    try
    {
        await WhenFileCreated(string path, cts.Token);
    }
    catch(TaskCanceledException)
    {
        //...
    }
}
0 голосов
/ 26 апреля 2018

Попробуйте изменить свой код, например, для установки этого тайм-аута.

var tcs = new TaskCompletionSource<TestResult>();

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

Более подробную информацию вы можете найти в: Тайм-аут для асинхронного метода, реализованного с помощью TaskCompletionSource

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...