首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ExecutionContext.Capture()和ExecutionContext.Run(上下文、工作、状态)的成本

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

Stack Overflow用户
提问于 2016-01-08 22:43:01
回答 1查看 978关注 0票数 5

有没有人知道它对ExecutionContext.Capture()ExecutionContext.Run(context, work, state)是否昂贵?

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

我之所以这样问,是因为我有一个ContextItem,在这里我保存上下文工作并在其中进行状态,以便稍后执行。因为我希望能够对在执行工作时可能抛出的异常作出反应,所以如果在工作中抛出异常,就会执行回退。我还有最后的工作,在任何情况下,如果抛出或不抛出异常,都会不加考虑地执行。由于我只能使用ExecutionContext一次,所以我必须对其中一个ContextItems进行三次ExecutionContext.Capture() .

还是这听起来是完全错误的做法?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-09 09:18:05

正如@Alois推荐的那样,我使用以下代码运行了一项测试,将锁定与捕获和排列的扩展进行比较:

代码语言:javascript
复制
class Program
{
    private static readonly object _lock = new object();
    private static readonly int numberOfItems = 1000000;
    private static readonly int _numberOfIterations = 1000000;

    private static void Main(string[] args)
    {
        MeasureTimeWithLocking();
        MeasureTimeWithCapuringContext();
        Console.WriteLine();
        MeasureTimeWithLocking();
        MeasureTimeWithCapuringContext();
        Console.WriteLine();
        MeasureTimeWithLocking();
        MeasureTimeWithCapuringContext();
        Console.ReadKey();
    }

    private static void MeasureTimeWithLocking()
    {
        List<ContextItem> items = new List<ContextItem>();
        Stopwatch stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < numberOfItems; i++)
        {
            ContextItem item = new ContextItem();
            item.Work1 = DoSomeWorkWithLock;
            item.Work2 = DoSomeWorkWithLock;
            item.Work3 = DoSomeWorkWithLock;
        }

        Parallel.ForEach(items, (item) =>
        {
            item.Work1(null);
            item.Work2(null);
            item.Work3(null);
        });
        stopwatch.Stop();
        Console.WriteLine("Time elapsed with locking:           " + stopwatch.Elapsed);
    }

    private static void MeasureTimeWithCapuringContext()
    {
        List<ContextItem> items = new List<ContextItem>();
        Stopwatch stopwatch = Stopwatch.StartNew();
        for (int i = 0; i < numberOfItems; i++)
        {
            ContextItem item = new ContextItem();
            item.Context1 = ExecutionContext.Capture();
            item.Context2 = ExecutionContext.Capture();
            item.Context3 = ExecutionContext.Capture();
            item.Work1 = DoSomeWork;
            item.Work2 = DoSomeWork;
            item.Work3 = DoSomeWork;
        }

        foreach (ContextItem item in items)
        {
            ExecutionContext.Run(item.Context1, item.Work1, null);
            ExecutionContext.Run(item.Context2, item.Work2, null);
            ExecutionContext.Run(item.Context3, item.Work3, null);
        }
        stopwatch.Stop();
        Console.WriteLine("Time elapsed with capturing context: " + stopwatch.Elapsed);
    }

    private static void DoSomeWork(object ignored)
    {
        Work();
    }


    private static void DoSomeWorkWithLock(object ignored)
    {
        lock (_lock)
        {
            Work();
        }
    }

    private static void Work()
    {
        int count = 0;
        for (int i = 0; i < _numberOfIterations; i++)
        {
            count ++;
        }
    }

    private class ContextItem
    {
        public ExecutionContext Context1 { get; set; }
        public ExecutionContext Context2 { get; set; }
        public ExecutionContext Context3 { get; set; }

        public ContextCallback Work1 { get; set; }
        public ContextCallback Work2 { get; set; }
        public ContextCallback Work3 { get; set; }
    }
}

结果如下:

因此,如果我做得对,捕获和执行排队平均要比锁定花费高出5倍。

同时也要回答我问题的一部分:

还是这听起来是完全错误的做法?

我在这篇文章上读到

如果你必须知道他们在那里,要么你在做一些超先进的事情,要么是出了问题。

如果您想了解ExecutionContext,那么推荐这篇文章作为最佳来源。在通过它并与一位同事一起运行一些测试之后,我意识到我使用的是ExecutionContext没有意义的地方,而且它比锁的性能更低,因此它可能也比其他线程功能/构造的性能更低。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34687336

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档