使用TaskCompletionSource.SetResult()将在一个线程上创建的非线程安全对象传递给另一个线程安全吗?
例如,在这个人为的例子中:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
public class Test
{
struct Info
{
public bool done;
public Dictionary<int, int> results;
}
public static void Main()
{
WaitForIt();
Console.ReadLine();
}
static async void WaitForIt()
{
TaskCompletionSource<Info> myTcs = new TaskCompletionSource<Info>();
Thread newThread = new Thread(new ParameterizedThreadStart(BackgroundThread));
newThread.Start(myTcs);
Info theInfo = await myTcs.Task;
Console.WriteLine(theInfo.done);
foreach (KeyValuePair<int, int> item in theInfo.results)
{
Console.WriteLine(item.Key + "=" + item.Value);
}
}
static void BackgroundThread(object tcs)
{
TaskCompletionSource<Info> theTcs = (TaskCompletionSource<Info>)tcs;
Info info = new Info();
info.done = true;
info.results = new Dictionary<int, int>();
info.results.Add(1, 2);
info.results.Add(3, 4);
theTcs.SetResult(info);
}
}由于信息和字典对象是在一个线程上创建的,传递给另一个线程,并且在创建线程上不再被访问,所以似乎不需要执行任何锁定。对象永远不会被多个线程同时访问。
是否需要一个记忆屏障?
读取线程是否保证具有与传递给SetResult()的创建线程完全相同的数据?
发布于 2015-09-18 01:55:59
使用TaskCompletionSource.SetResult()将在一个线程上创建的非线程安全对象传递给另一个线程安全吗?
是的,只要对象可以在不同的线程上使用(当然,这是在一个线程上创建的)。
是否需要一个记忆屏障?
不是的。接收线程中的await将为您处理这个问题。
不过,我必须指出,Thread的使用听起来更像1990年的代码,而不是2015年的代码。你真的应该用Task.Run代替。而且由于Task.Run已经理解了结果类型,所以TaskCompletionSource<T>根本没用。哦,你应该避免async void
public static void Main()
{
WaitForItAsync().Wait();
Console.ReadLine();
}
static async Task WaitForItAsync()
{
Info theInfo = await Task.Run(() => CreateInfo());
Console.WriteLine(theInfo.done);
foreach (KeyValuePair<int, int> item in theInfo.results)
{
Console.WriteLine(item.Key + "=" + item.Value);
}
}
static Info CreateInfo()
{
Info info = new Info();
info.done = true;
info.results = new Dictionary<int, int>();
info.results.Add(1, 2);
info.results.Add(3, 4);
return info;
}https://stackoverflow.com/questions/32635305
复制相似问题