【发布时间】:2020-10-11 11:14:22
【问题描述】:
这只是一个自我学习的情况。我对 TPL 和线程很陌生。无论如何,我正在使用一个通用的 Singleton 类并创建 ~10K 实例来检查我的代码是否每次都返回相同的实例或创建新实例。我在 for 循环中使用任务工厂异步创建实例。为了验证实例的创建,我返回了一个字符串,其中包含这些信息作为字符串列表:
- 迭代计数器
- 实例名称
- 实例的哈希码和
- 线程 ID 并将字符串列表显示到列表框。
我的查询
在跑步中,我发现了一些东西,
- for 循环中 i 的值因不同的实例而重复
- 对于那些 10K 迭代,我只创建了 8-9 个线程,而不是预期的 10k 线程。我期待 10K 线程弹出,完成各自的任务,然后优雅地消失。
- 我可以在我的项目中使用它作为类库,而不管平台是 Web、Windows 还是移动?
请在我的 1OK 线程想法上留言 :)。在多线程方面是好主意还是坏主意?
我的代码
单例类
public sealed class Singleton<T> where T : class
{
static Singleton() { }
private Singleton() { }
public static T Instance { get; } = Activator.CreateInstance<T>();
}
类:SingletonInThread
public class SingletonInThread
{
/// <summary>
/// Method responsible for creation of same instance, 10K times using Task.Factory.StartNew()
/// </summary>
/// <returns></returns>
public async Task<IEnumerable<string>> LoopAsync()
{
List<Task<string>> list = new List<Task<string>>();
for (int i = 0; i <= 9999; i++)
{
list.Add(Task.Factory.StartNew(()=> CreateAndLogInstances(i)));
}
return await Task.WhenAll<string>(list);
}
/// <summary>
/// Creates new instance of Logger and logs its creation with few details. Kind of Unit of Work.
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
private string CreateAndLogInstances(int i)
{
var instance = Singleton<Logger>.Instance;
return $"Instance{i}. Name of instance= {instance.ToString()} && Hashcode ={instance.GetHashCode()} && ThreadId= {Thread.CurrentThread.ManagedThreadId}";
}
}
前端 _ 在 UI 方面,在 buttonclick 事件中,填充列表框
private async void button1_Click(object sender, EventArgs e)
{
IEnumerable<string> list = await new SingletonInThread().LoopAsync();
foreach (var item in list)
{
listBox1.Items.Add(item);
}
}
另外,我注意到在用 10K 项填充列表框时,我的 UI 被阻塞了。请帮我以异步方式填充它。我认识 bgworker、begininvoke 和 methodinvoker。 TPL里除了too还有什么??
输出
---
更新
按照建议,如果我使用 Parallel.For,那么,我得到的不是 10K 字符串,而是 9491、9326 等的随机数字。即小于 10K。不知道为什么???
这是我使用 Parallel.For 的 LoopAsync 方法的更新代码
public IEnumerable<string> LoopAsync()
{
List<string> list = new List<string>();
Parallel.For(0, 9999, i =>
{
list.Add( CreateAndLogInstances(i));
});
return list;
}
【问题讨论】:
-
必读:csharpindepth.com/Articles/Singleton。此外,使用 async/await 进行并行处理是一个非常奇怪的选择,我建议您改用 Parallel.For 和 Parallel.ForEach 方法
-
@CamiloTerevinto 请看一看。仍然存在问题
-
你需要捕获
i:var index = i; list.Add( CreateAndLogInstances(index));
标签: c# multithreading async-await task-parallel-library .net-4.7.2