Самоотменяющаяся задача блокирует другие экземплярыC#

Место общения программистов C#
Ответить
Anonymous
 Самоотменяющаяся задача блокирует другие экземпляры

Сообщение Anonymous »

Я пытаюсь создать подкласс Task, который отменяет сам себя и ждет, когда он будет удален.
Во время модульного тестирования я получил странные неудачные тестовые случаи. В конце концов все свелось к повторению; Я мог бы даже запустить один и тот же тест несколько раз и получить положительный результат только при первом запуске.
Вот код моего класса AutoCancelTask ​​(извините за довольно длинный код... Я пытался создайте минимальный функциональный пример, который вы сможете скопировать и вставить...):

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

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

namespace Tests
{
/// 
/// A Task that is cancelled and waited for, when disposed.
/// 
public class AutoCancelTask : Task
{
private readonly CancellationTokenSource _cts;

private AutoCancelTask(Action action, CancellationTokenSource cts, TaskCreationOptions options)
: base(() => action(cts.Token), cts.Token, options)
{
_cts = cts;
}

/// 
/// Wrap a cancellable Action in a Task that is automatically cancelled and waited for when disposed.
/// 
/// The Action to wrap.
/// The TaskCreationOptions to use.
/// The started task.
public static Task Run(Action action, TaskCreationOptions options = TaskCreationOptions.None)
{
Task t = new AutoCancelTask(action, new CancellationTokenSource(), options);
t.Start();
return t;
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
try
{
_cts.Cancel();
}
catch (ObjectDisposedException)
{
// nothing to do in this case
}
try
{
Wait();
}
catch (ObjectDisposedException) { }
catch (AggregateException ex)
{
if (1 < ex.InnerExceptions.Count || false == (ex.InnerExceptions[0] is TaskCanceledException))
{
// rethrow if the aggregate does not contain a single TaskCancelledException
throw ex;
}
}
_cts.Dispose();
}

base.Dispose(disposing);
}
}
}
А вот мой тестовый класс

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

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;

namespace Tests
{
public class TestDataWrapper
{
internal bool? IsCancelled { get; private set; } = null;
internal void Action(CancellationToken cancel)
{
IsCancelled = Task.Delay(100, cancel).ContinueWith(t => t.IsCanceled).Result;
}
}

[TestClass()]
public class Tests
{
public static IEnumerable Datas { get; } =
Enumerable.Range(0, 5).Select(_ => new object[] { new TestDataWrapper() });

[DataTestMethod]
[DynamicData(nameof(Datas))]
public void AutoCancelTask_Cancels(TestDataWrapper data)
{
using (AutoCancelTask.Run(data.Action)) { }
Assert.AreEqual(true, data.IsCancelled);
}
}
}
Очевидно, я ожидаю, что тестовый пример пройдет успешно. Однако проходит только первое выполнение, а остальные завершаются с ошибкой с сообщением Assert.AreEqual. Ожидается: . Фактически:..
Интересно, что время выполнения также варьируется:
Выполнение 1: ~30 мс
Выполнение 2: ~300 мсВыполнение 4-5:

Подробнее здесь: https://stackoverflow.com/questions/790 ... -instances
Ответить

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

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

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

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

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