【发布时间】:2018-08-02 07:06:00
【问题描述】:
您好,我有以下问题:
我想执行类似于事务的操作。我想在收到外部触发器后执行许多 async 操作。因此,我使用在表示触发器的方法中设置的 TaskCompletionSource:TriggerTransaction。
此触发器方法获取当我按下特定的控制台键时,在线程池中调用 Main。
在我按下A 关键字后,TriggerTransaction 被执行,TaskCompletionSource-s 被设置。仍然主线程不计算两个等待任务的总和。
class Program
{
public static Task<Task<int>> TransactionOperation1()
{
TaskCompletionSource<Task<int>> tcs = new TaskCompletionSource<Task<int>>();
tasks.Add(tcs);
Task<Task<int>> result = tcs.Task;
return result;
}
public static Task<Task<int>> TransactionOperation2()
{
TaskCompletionSource<Task<int>> tcs = new TaskCompletionSource<Task<int>>();
tasks.Add(tcs);
Task<Task<int>> result = tcs.Task;
return result;
}
public static async Task<int> ExecuteTransactionOnDB()
{
await Task.Delay(1000);
return 5;
}
public static async Task TriggerTransaction()
{
int value = await ExecuteTransactionOnDB();
foreach (var item in tasks)
{
item.SetResult(value);
}
}
public static List<dynamic> tasks = new List<dynamic>();
static async Task Main(string[] args)
{
Task<Task<int>> a = TransactionOperation1();
Task<Task<int>> b = TransactionOperation2();
Task.Run(async() =>
{
while (Console.ReadKey().Key != ConsoleKey.A) ;
await TriggerTransaction();
});
if (!File.Exists("D:\\data.txt"))
{
File.Create("D:\\data.txt");
}
using(FileStream stream=new FileStream("data.txt",FileMode.Append,FileAccess.Write))
{
int sum=await await a + await await b;//thread wont pass this line when tasks are set.
ReadOnlyMemory<byte> bytes = Encoding.UTF8.GetBytes(sum);
stream.Write(bytes.ToArray());
}
Console.WriteLine(await await a + await await b);
}
}
}
PS 如果你想知道我为什么使用List<dynamic> 来存储TaskCompletionSource-s,那是因为TransactionOperations 的返回类型不同。其中一些会返回int ,其他人String..Bool..etc.
为了更好地理解,我做了一个架构-
如您所见,有:
-我要存储 TCS-es 的列表
- 一些只有在设置外部触发器后才完成的调用(事务已执行)
正如您在Calls 中看到的,都有不同的返回类型。
【问题讨论】:
-
我想你可能误解了一些东西。很少需要创建
TaskCompletionSources(除了将 EAP 异步 API 适配到 TAP 之外)。包装其他任务的任务通常也很少是正确的。不幸的是,您的大部分代码似乎都是关于做这两件事,所以我什至无法说出您要解决的问题是什么是。 -
@BercoviciAdrian 这看起来像XY problem。您有一个问题 X 并认为 Y 是解决方案,多个 TCS 和一个列表?当这不起作用时,你问的是 X,而不是 Y。你想要解决的真正问题是什么?可以用简单的
await Task.WhenAll()解决吗?还是一些ActionBlock<T>实例? -
如果我有一个
Task<int>和一个Task<bool>我如何使用Task.WhenAll并同时获取两个结果? -
@BercoviciAdrian 你到底想做什么?这与事务无关 - 完成或回滚的原子操作。事务与任务无关。你的问题是关于你如何尝试解决一些问题,而不是问题本身
-
如果您想要交易,请检查 TransactionScope。如果您想实现自己的事务对象(它们被称为“资源管理器”),您需要实现IEnlistmentNotification。这个article 展示了如何做到这一点,它比听起来容易
标签: c# async-await task taskcompletionsource