你好,我有以下问题:
我想执行类似于事务的操作。我希望在收到外部async后执行许多trigger.Therefore操作,我使用的是在表示触发器:TriggerTransaction的方法中设置的TaskCompletionSource。
当我按下特定的控制台键时,将在线程池的Main中调用此触发器方法。
在我按下A关键字后,执行TriggerTransaction和TaskCompletionSource-s get set.Still后,主线程不会计算两个等待任务的总和。
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);
}
}
}P.S如果你想知道我为什么要用List<dynamic>来存储TaskCompletionSource-s,那是因为TransactionOperations的回报是不同的,type.Some会返回int,其他的会返回String .Bool..etc。
为了更好地理解,我制定了一个模式-正如您将看到的那样:
要存储TCS-es的-A列表。
仅在设置外部触发器(执行事务)后才完成的-Some调用
正如您在Calls中所看到的,所有这些都有不同的返回类型。

发布于 2018-08-02 07:58:23
你为什么需要一个Task<Task<int>>?简单地说,Task<int>就足够了,因此,TaskCompletionSource<int>就足够了。您还可以去掉一个尴尬的await await ...,这在您的情况下也不是必需的。
注意,我还将Close()添加到File.Create()返回的流中。
以下是该程序的工作版本:
class Program
{
public static Task<int> TransactionOperation1()
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
tasks.Add(tcs);
return tcs.Task;
}
public static Task<int> TransactionOperation2()
{
TaskCompletionSource<int> tcs = new TaskCompletionSource<int>();
tasks.Add(tcs);
return tcs.Task;
}
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<int> a = TransactionOperation1();
Task<int> b = TransactionOperation2();
Task input = Task.Run(async () => {
while (Console.ReadKey().Key != ConsoleKey.A);
await TriggerTransaction();
});
if (!File.Exists("C:\\temp\\data.txt"))
{
File.Create("C:\\temp\\data.txt").Close();
}
using (FileStream stream = new FileStream("C:\\temp\\data.txt", FileMode.Append, FileAccess.Write))
{
int sum = await a + await b; // now it works ok
var bytes = Encoding.UTF8.GetBytes(sum.ToString());
stream.Write(bytes);
}
Console.WriteLine(await a + await b);
}
}发布于 2018-08-02 08:13:20
检查修改后的代码版本,它将通过执行使用Task创建的TaskCompletionSource生成预期的结果。我也将代码设置为通用代码,这样您就不需要在编译时使用dynamic类型并定义数据类型了
static async Task Main(string[] args)
{
var a = Program<int>.TransactionOperation1();
var b = Program<int>.TransactionOperation2();
await Task.Run(async() =>
{
Console.ReadLine();
await Program<int>.TriggerTransaction(5);
});
if (!File.Exists("D:\\data.txt"))
{
File.Create("D:\\data.txt");
}
using (FileStream stream = new FileStream("D:\\data.txt", FileMode.Append, FileAccess.Write))
{
int sum = await a + await b;//thread wont pass this line when tasks are set.
var bytes = Encoding.UTF8.GetBytes(sum.ToString());
stream.Write(bytes, 0, bytes.Length);
}
Console.WriteLine(await a + await b);
}
class Program<T>
{
public static Task<T> TransactionOperation1()
{
var tcs = new TaskCompletionSource<T>();
tasks.Add(tcs);
return tcs.Task;
}
public static Task<T> TransactionOperation2()
{
var tcs = new TaskCompletionSource<T>();
tasks.Add(tcs);
return tcs.Task;
}
public static async Task<T> ExecuteTransactionOnDB(T t)
{
return await Task.FromResult(t);
}
public static async Task TriggerTransaction(T t)
{
T value = await ExecuteTransactionOnDB(t);
foreach (var item in tasks)
{
item.SetResult(value);
}
}
public static List<TaskCompletionSource<T>> tasks = new List<TaskCompletionSource<T>>();
}以下是重要的修改:
List<dynamic>被List<TaskCompletionSource<T>>取代TransactionOperation1/2有返回类型Task<T>,这是使用TaskCompletionSource<T>创建的任务Task.Run中添加了一个额外的等待,它在内部执行TriggerTransaction,但是您可以替换以下代码:
等待Task.Run(异步() => { Console.ReadLine();等待Program.TriggerTransaction(5);});
用await Program<int>.TriggerTransaction(5);现在,正如您所期望的那样,它将产生结果,它将总结这两个整数。很少有更多的小更改,比如删除不需要的Task.Delay。
编辑1-使用Task.WhenAll
static async Task Main(string[] args)
{
var a = Program.TransactionOperation1(5);
var b = Program.TransactionOperation1(5);
Console.ReadLine();
var taskResults = await Task.WhenAll(a,b);
dynamic finalResult = 0;
foreach(var t in taskResults)
finalResult += t;
if (!File.Exists("D:\\data.txt"))
{
File.Create("D:\\data.txt");
}
using (FileStream stream = new FileStream("D:\\data.txt", FileMode.Append, FileAccess.Write))
{
var bytes = Encoding.UTF8.GetBytes(finalResult.ToString());
stream.Write(bytes, 0, bytes.Length);
}
Console.WriteLine(finalResult);
}
class Program
{
public static Task<dynamic> TransactionOperation1(dynamic val)
{
return Task<dynamic>.Run(() => val);
}
public static Task<dynamic> TransactionOperation2(dynamic val)
{
return Task<dynamic>.Run(() => val);
}
}https://stackoverflow.com/questions/51647468
复制相似问题