fos*_*ose 6 .net c# performance multithreading
有谁知道,如果它是昂贵的ExecutionContext.Capture()和 ExecutionContext.Run(context, work, state)?
它是否会降低性能,因此建议小心使用?
我问,因为我有一个ContextItem,我将Context工作和状态保存在以后执行.因为我希望能够对执行工作时可能抛出的异常作出反应,所以如果在工作中抛出异常,我会执行回退.而且我也有最后的工作,无论如何抛出异常都会在任何情况下执行.因为我只能使用一次ExecutionContext,所以我必须为ExecutionContext.Capture()这些ContextItem之一使用三次......
或者这听起来像一个完全错误的方法?
根据 @Alois Kraus 的建议,我使用以下代码进行了测试,比较锁定与捕获和排队执行:
\n\nclass Program\n{\n private static readonly object _lock = new object();\n private static readonly int numberOfItems = 1000000;\n private static readonly int _numberOfIterations = 1000000;\n\n private static void Main(string[] args)\n {\n MeasureTimeWithLocking();\n MeasureTimeWithCapuringContext();\n Console.WriteLine();\n MeasureTimeWithLocking();\n MeasureTimeWithCapuringContext();\n Console.WriteLine();\n MeasureTimeWithLocking();\n MeasureTimeWithCapuringContext();\n Console.ReadKey();\n }\n\n private static void MeasureTimeWithLocking()\n {\n List<ContextItem> items = new List<ContextItem>();\n Stopwatch stopwatch = Stopwatch.StartNew();\n for (int i = 0; i < numberOfItems; i++)\n {\n ContextItem item = new ContextItem();\n item.Work1 = DoSomeWorkWithLock;\n item.Work2 = DoSomeWorkWithLock;\n item.Work3 = DoSomeWorkWithLock;\n }\n\n Parallel.ForEach(items, (item) =>\n {\n item.Work1(null);\n item.Work2(null);\n item.Work3(null);\n });\n stopwatch.Stop();\n Console.WriteLine("Time elapsed with locking: " + stopwatch.Elapsed);\n }\n\n private static void MeasureTimeWithCapuringContext()\n {\n List<ContextItem> items = new List<ContextItem>();\n Stopwatch stopwatch = Stopwatch.StartNew();\n for (int i = 0; i < numberOfItems; i++)\n {\n ContextItem item = new ContextItem();\n item.Context1 = ExecutionContext.Capture();\n item.Context2 = ExecutionContext.Capture();\n item.Context3 = ExecutionContext.Capture();\n item.Work1 = DoSomeWork;\n item.Work2 = DoSomeWork;\n item.Work3 = DoSomeWork;\n }\n\n foreach (ContextItem item in items)\n {\n ExecutionContext.Run(item.Context1, item.Work1, null);\n ExecutionContext.Run(item.Context2, item.Work2, null);\n ExecutionContext.Run(item.Context3, item.Work3, null);\n }\n stopwatch.Stop();\n Console.WriteLine("Time elapsed with capturing context: " + stopwatch.Elapsed);\n }\n\n private static void DoSomeWork(object ignored)\n {\n Work();\n }\n\n\n private static void DoSomeWorkWithLock(object ignored)\n {\n lock (_lock)\n {\n Work();\n }\n }\n\n private static void Work()\n {\n int count = 0;\n for (int i = 0; i < _numberOfIterations; i++)\n {\n count ++;\n }\n }\n\n private class ContextItem\n {\n public ExecutionContext Context1 { get; set; }\n public ExecutionContext Context2 { get; set; }\n public ExecutionContext Context3 { get; set; }\n\n public ContextCallback Work1 { get; set; }\n public ContextCallback Work2 { get; set; }\n public ContextCallback Work3 { get; set; }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n结果是:
\n\n\n\n因此,如果我做得正确,捕获和执行排队的成本平均比锁定高 5 倍左右。
\n\n也回答我的问题的一部分:
\n\n\n\n\n或者这听起来是一种完全错误的方法吗?
\n
我在这篇文章中读到
\n\n\n\n\n如果你必须知道它们\xe2\x80\x99在那里,要么你\xe2\x80\x99正在做一些超级先进的事情,要么\xe2\x80\x99出了问题。
\n
如果您想了解 ExecutionContext,那么这篇文章被推荐为最佳来源。\n在浏览完它并与同事一起运行一些测试后,我意识到我正在使用 ExecutionContext,但它没有\xe2\x80\x99t 的意义,加上它的性能比锁低,因此它的性能也可能比其他线程功能/结构低。
\n