首页 > 解决方案 > 无法获取 TaskCompletionSource 的结果

问题描述

你好我有以下问题:

我想执行类似于事务的操作。我想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如果你想知道为什么我确实使用 aList<dynamic>来存储TaskCompletionSource-s ,那是因为 TransactionOperations 的返回类型会有所不同。其中一些会返回int,其他String.. ..etc Bool

为了更好地理解,我制作了一个架构-正如您将看到的那样:
-我要存储 TCS-es 的列表-
仅在设置外部触发器后才完成的某些调用(事务已执行)
您可以在 中看到Calls,都有不同的返回类型。
在此处输入图像描述

标签: c#async-awaittasktaskcompletionsource

解决方案


为什么你需要一个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);
    }
}

推荐阅读