【发布时间】:2021-12-04 20:06:54
【问题描述】:
我编写了一个线程测试应用程序来查看多个并行启动的线程返回的行为。我是异步编程的新手,请您对此代码发表评论吗?
我使用 Parallel 创建了多个 TestThreadClass 实例,以查看异步操作同时完成时发生的情况。线程完成后,我将它们添加到线程安全字典 (ConcurrentDictionary) 中,其中包含随机生成的 guid。
下面是一个随机异步类在 1 毫秒内返回;
public class TestThreadClass
{
private Task<ThreadResultModel> myTask;
public readonly int myNumber;
public readonly string myId;
public TestThreadClass(int _myNumber)
{
myNumber = _myNumber;
myId = Guid.NewGuid().ToString();
}
public async Task<ThreadResultModel> StartOperation()
{
myTask = InvokeOperation();
return await myTask;
}
private async Task<ThreadResultModel> InvokeOperation()
{
await Task.Delay(TimeSpan.FromMilliseconds(1));
return new ThreadResultModel(myNumber, myId, "Returned");
}
}
下面是我使用 WinForms 应用程序的创建者类。我启动并行线程,并在它们完成后将它们填充到 GridView 以比较返回毫秒数;
public partial class Form1 : Form
{
private const int threadNumber = 100;
private readonly ConcurrentDictionary<string, ThreadResultModel> startedConcurrentDictionary;
private readonly ConcurrentDictionary<string, ThreadResultModel> returnedConcurrentDictionary;
public Form1()
{
InitializeComponent();
startedConcurrentDictionary = new ConcurrentDictionary<string, ThreadResultModel>();
returnedConcurrentDictionary = new ConcurrentDictionary<string, ThreadResultModel>();
}
private void Form1_Load(object sender, EventArgs e)
{
FillComboboxes();
}
private void FillComboboxes()
{
for (int i = 1; i <= threadNumber; i++)
{
DdlThreadNumber.Items.Add(i.ToString());
}
}
private void BtnStartThreads_Click(object sender, EventArgs e)
{
Parallel.For(0, int.Parse(DdlThreadNumber.Text), StartAThread);
}
private void StartAThread(int threadTag)
{
TestThreadClass t = new TestThreadClass(threadTag);
startedConcurrentDictionary.TryAdd(t.myId, new ThreadResultModel(threadTag, t.myId, "Started"));
t.StartOperation().ContinueWith(result =>
{
returnedConcurrentDictionary.TryAdd(result.Result.MyId, result.Result);
});
}
private void BtnReport_Click(object sender, EventArgs e)
{
foreach (var item in startedConcurrentDictionary)
{
GrdThreads.Rows.Add(item.Value.MyNumber, item.Value.MyId, item.Value.EventType, item.Value.Time);
}
foreach (var item in returnedConcurrentDictionary)
{
GrdThreads.Rows.Add(item.Value.MyNumber, item.Value.MyId, item.Value.EventType, item.Value.Time);
}
}
private void GrdThreads_SelectionChanged(object sender, EventArgs e)
{
statusLabel.Text = GrdThreads.SelectedRows.Count.ToString();
}
}
我只是想知道这种方法是否正确。
【问题讨论】:
-
请注意
Parallel.Foris not async friendly。您可以查看here 的替代方案。还将ContinueWith与awaitis not a good idea 结合起来,因为这两种机制完成了同样的事情。使用其中一种,最好使用await。 -
@TheodorZoulias 实际上,在这种情况下,
Parallel.For调用了void方法,这也不是async,所以这不是一个大问题 -
@karolgro 你是对的,
Parallel.For调用了一个void方法,但整个代码充分说明了作者的意图,即并行化多个异步操作。不幸的是,他们认为Parallel.For是解决此问题的正确工具,但事实并非如此。Parallel.ForEachAsync是,但尚未发布。
标签: c# multithreading asynchronous