C# – использование асинхронной задачи для создания исключения через некоторое времяC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 C# – использование асинхронной задачи для создания исключения через некоторое время

Сообщение Anonymous »

Я пытаюсь создать механизм принудительного таймаута, который работает асинхронно.
В идеале мне нужно запустить задачу, не дожидаясь ее, и я ожидаю, что через некоторое время она выдаст исключение, имитирующее таймаут.
Моя проблема в том, что я не могу изменить способ вызова методов в основном потоке и могу просто добавлять туда методы.
Я также знаю что исключения, возникающие в асинхронных задачах, которые не ожидаются, никогда не перехватываются в основном потоке. Но это именно то, что мне нужно, и я не могу найти решение.
Чтобы проиллюстрировать мою проблему, приведу следующий код:

Код: Выделить всё

        using System;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
class Program
{
//Main method which I don't have control over, to change how other methods are called, I can only add methods here.
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
try
{
//Forced timeout
Console.Write("Init timeout \n");
var forcedTimeout = myForcedTimeoutMethod(1000);

//Do something that might be long
//Just pretending the main thread is still doing some work that should take longer than 1 second
AsyncUtil.RunSync(() => ForcedTimeoutContext.Wait(2000));

Console.Write("Method finished \n");
forcedTimeout.Dispose();

}
catch (Exception e)
{
Console.Write("Exception caught: " + e.Message);
}
}

public static ForcedTimeoutContext myForcedTimeoutMethod(int TimeInMs)
{

ForcedTimeoutContext forcedTimeout = new ForcedTimeoutContext();
forcedTimeout.TokenSource = new CancellationTokenSource();

forcedTimeout.Task = Task.Run(async delegate
{

await Task.Delay(TimeSpan.FromMilliseconds(TimeInMs), forcedTimeout.TokenSource.Token);
forcedTimeout.TokenSource.Token.ThrowIfCancellationRequested();
throw new Exception("Forced timeout reached");
});

return forcedTimeout;
}
}

//Context class to be able to Dispose and cancel the timeout if needed
class ForcedTimeoutContext : IDisposable
{
public CancellationTokenSource TokenSource;
public Task Task;

public void Dispose()
{
if (TokenSource != null)
TokenSource.Dispose();
if (Task != null)
Task.Dispose();
}

public static async Task Wait(int ssms)
{
await Task.Delay(ssms);
return true;
}
}

//Utility helper to run async methods synchronously
public class AsyncUtil
{
private static readonly TaskFactory taskFactory = new TaskFactory(
CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);

public static TResult RunSync(Func  task) =>
taskFactory
.StartNew(task)
.Unwrap()
.GetAwaiter()
.GetResult();
}
}
Как и ожидалось, поскольку задача в функции myForcedTimeoutMethod не ожидается, исключение «Достигнуто принудительное время ожидания» никогда не перехватывается основным потоком.
Я также пробовал использовать Task.Run().ContinueWith(...), но продолжение также выполняется в другой области.
Ближайшее решение, которого мне удалось достичь, было использовать Thread.Interrupt() следующим образом:

Код: Выделить всё

                public static  ForcedTimeoutContext myForcedTimeoutMethod(int TimeInMs)
{

ForcedTimeoutContext forcedTimeout = new ForcedTimeoutContext();
forcedTimeout.TokenSource = new CancellationTokenSource();
var currThread = Thread.CurrentThread;

forcedTimeout.Task = Task.Run(async delegate
{

await Task.Delay(TimeSpan.FromMilliseconds(TimeInMs), forcedTimeout.TokenSource.Token);
currThread.Interrupt();
});

return forcedTimeout;
}
}
Однако в этом случае у меня нет никакого контроля над исключением, и я хочу иметь возможность генерировать конкретное исключение.
Есть есть ли способ вызвать исключение в основном потоке из асинхронной задачи, не дожидаясь его?

Подробнее здесь: https://stackoverflow.com/questions/786 ... -some-time
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»