ExecutionContext.Capture()和ExecutionContext.Run(上下文,工作,状态)的成本

fos*_*ose 6 .net c# performance multithreading

有谁知道,如果它是昂贵的ExecutionContext.Capture()ExecutionContext.Run(context, work, state)

它是否会降低性能,因此建议小心使用?

我问,因为我有一个ContextItem,我将Context工作和状态保存在以后执行.因为我希望能够对执行工作时可能抛出的异常作出反应,所以如果在工作中抛出异常,我会执行回退.而且我也有最后的工作,无论如何抛出异常都会在任何情况下执行.因为我只能使用一次ExecutionContext,所以我必须为ExecutionContext.Capture()这些ContextItem之一使用三次......

或者这听起来像一个完全错误的方法?

fos*_*ose 1

根据 @Alois Kraus 的建议,我使用以下代码进行了测试,比较锁定与捕获和排队执行:

\n\n
class 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}\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果是:

\n\n

在此输入图像描述

\n\n

因此,如果我做得正确,捕获和执行排队的成本平均比锁定高 5 倍左右。

\n\n

也回答我的问题的一部分:

\n\n
\n

或者这听起来是一种完全错误的方法吗?

\n
\n\n

我在这篇文章中读到

\n\n
\n

如果你必须知道它们\xe2\x80\x99在那里,要么你\xe2\x80\x99正在做一些超级先进的事情,要么\xe2\x80\x99出了问题。

\n
\n\n

如果您想了解 ExecutionContext,那么这篇文章被推荐为最佳来源。\n在浏览完它并与同事一起运行一些测试后,我意识到我正在使用 ExecutionContext,但它没有\xe2\x80\x99t 的意义,加上它的性能比锁低,因此它的性能也可能比其他线程功能/结构低。

\n