通过多线程提高性能
我现在正在尝试通过使其多线程来提高 winform 应用程序的性能。目前该类如下所示:
public class MainClass
{
List<DataItem> data; //thousands of DataItem, but each is independent
//and a lot of non-thread-safe variables here,variable1 variable2 ...
public void Go()
{
data.ForEach(item => DealWithDataItem(item));
}
public void DealWithDataItem(DataItem item)
{
//costs really long time here
Step1(item);
Step2(item); //and a lot of StepN(item)
}
public void StepN(DataItem item)
{
//variable1 = blabla
//variable2 = blabla ..etc
}
}
我想为每个 DataItem 使用 ThreadPool。
data.ForEach(item => ThreadPool.QueueUserWorkItem( s => DealWithDataItem(item) ));
但这么多非线程安全变量!我无法在某些方法中声明它们,因为它在 StepN
方法之间共享。而且让它们全部都是线程安全的非常困难!我做错了什么吗?有什么好的解决办法吗?谢谢!
I'm now trying to improve a winform application's performance by make it multi-threaded. Currently the class looks like:
public class MainClass
{
List<DataItem> data; //thousands of DataItem, but each is independent
//and a lot of non-thread-safe variables here,variable1 variable2 ...
public void Go()
{
data.ForEach(item => DealWithDataItem(item));
}
public void DealWithDataItem(DataItem item)
{
//costs really long time here
Step1(item);
Step2(item); //and a lot of StepN(item)
}
public void StepN(DataItem item)
{
//variable1 = blabla
//variable2 = blabla ..etc
}
}
I want to use ThreadPool
for each DataItem.
data.ForEach(item => ThreadPool.QueueUserWorkItem( s => DealWithDataItem(item) ));
But so many non-thread-safe variables! I can't declare them in some method, because it's shared between StepN
methods. And it's quite hard to make them all thread-safe! Am I doing anything wrong? Any good solutions? Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
尝试使用 ParallelEnumerable.AsParallel。
它将根据处理器/内核的数量自动创建线程。
唯一的问题是它包含在 Framework 4.0 中。
有关 PLINQ 的详细信息。 (正如andras评论的那样:对于framwork 3.5,它可以作为独立的反应式扩展 (Rx))
UPD:正如 0xA3 所说,强烈建议重构代码,使每个项目都有自己的计算变量。
我建议你将计算逻辑提取到DataItem中
,或者创建像“Calculator”这样的特殊类,这将完成所有工作,因此DataItem只会存储数据,计算逻辑将包含在Calculator类中。
其中 Calculator 类是这样的
Try using ParallelEnumerable.AsParallel.
It will automatically create threads depending on amount of processors / cores.
The only problem, that it's included in Framework 4.0.
More info about PLINQ. (And as andras commented: for framwork 3.5 it is available as stand-alone Reactive Extensions (Rx))
UPD: as 0xA3 said, refactoring code, making each item have it's own calc variables is strongly recommended.
I suggest you to extract calculation logics to DataItem
Or create special class like "Calculator", which would be do all the work, so DataItem would only store data, and logics of calculations would be contained in Calculator class.
where Calculator class is something like this
最好的方法可能是重构代码,以便摆脱不同数据项之间共享的所有字段。
更改(或子类化)
DataItem
类以包含用于操作dataItem
的所有相关数据和方法,以便您的代码更改为如下所示:Probably the best way would be to refactor your code, so that you get rid of all that fields shared between the different data items.
Change (or subclass) the
DataItem
class to contain all the relevant data and methods for manipulating adataItem
, so that your code changes to something like this:由于每个 DataItem 都是独立的,因此将工作移至新的 DataItem 工作方法中,并让每个实例自行处理:
Since each DataItem is independent, move the work into a new DataItem worker method, and let each instance deal with itself:
MainClass
在你的 GUI 线程中吗?您不应该在 GUI 线程中进行任何数据处理;在单独的线程中运行MainClass
。如何做到这一点?这完全取决于您未向我们展示的
blabla
内容。MainClass
需要返回结果吗?使用BeginInvoke
/EndInvoke
。您需要更新 GUI 吗?使用BackgroundWorker。如果您想要更好的答案,您必须向我们提供更多信息。Is
MainClass
in your GUI thread? You should not be doing any data processing in your GUI thread; runMainClass
in a separate thread.How to do this? That depends entirely on the
blabla
stuff you have not shown us. DoesMainClass
need to return a result? UseBeginInvoke
/EndInvoke
. Do you need to update the GUI? UseBackgroundWorker
. If you want a better answer you will have to give us more information.