Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ExecutionContext.Capture()和ExecutionContext.Run(上下文、工作、状态)的成本_C#_.net_Multithreading_Performance - Fatal编程技术网

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

C# ExecutionContext.Capture()和ExecutionContext.Run(上下文、工作、状态)的成本,c#,.net,multithreading,performance,C#,.net,Multithreading,Performance,有人知道ExecutionContext.Capture()和ExecutionContext.Run(context、work、state)的成本是否很高吗 它是否会降低性能,因此建议谨慎使用 我这样问是因为我有一个ContextItem,我在其中保存上下文工作和状态,以便稍后执行。因为我希望能够对执行工作时可能抛出的异常做出反应,所以如果在工作中抛出异常,我会执行一个回退。我还有最后的工作,不管是否抛出异常,在任何情况下都会毫不在意地执行。 因为我只能使用ExecutionContext一次

有人知道
ExecutionContext.Capture()
ExecutionContext.Run(context、work、state)
的成本是否很高吗

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

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


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

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

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; }
    }
}
类程序
{
私有静态只读对象_lock=new object();
私有静态只读int numberOfItems=1000000;
私有静态只读int_numberOfIterations=1000000;
私有静态void Main(字符串[]args)
{
使用锁定()测量时间;
MeasureTimeWithCapuringContext();
Console.WriteLine();
使用锁定()测量时间;
MeasureTimeWithCapuringContext();
Console.WriteLine();
使用锁定()测量时间;
MeasureTimeWithCapuringContext();
Console.ReadKey();
}
私有静态空隙测量带锁定()
{
列表项=新列表();
秒表秒表=Stopwatch.StartNew();
对于(int i=0;i
{
项目1(空);
第2项工作(空);
第3项工作(空);
});
秒表;
Console.WriteLine(“锁定时经过的时间:“+秒表.经过”);
}
私有静态void MeasureTimeWithCapuringContext()
{
列表项=新列表();
秒表秒表=Stopwatch.StartNew();
对于(int i=0;i
结果如下:

所以,如果我做得对的话,捕获和执行排队平均比锁定要贵5倍

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

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

我读了那本书

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

如果您想了解ExecutionContext,这篇文章被推荐为最佳来源。
在与同事一起检查并运行了一些测试后,我意识到我使用的ExecutionContext没有意义,而且它的性能不如锁,因此它的性能可能也不如其他线程功能/结构。

,不加评论的否决票是没有任何帮助的…@cory nelson所以如果我能用锁解决问题,它会更便宜吗?老实说,我认为说一个问题不好是不公平的,因为stackoverflow的Executiocontext没有一个问题讨论使用它是否昂贵,也没有我在网上找到的关于这个主题的页面。所以你说如果我不知道什么或者我不理解一个解释,我就不应该问问题?那么这个网站的意义何在?你发布的代码就是你所需要的。在1000万次迭代中加入一个for循环,然后自己检查。成本是否合适取决于你是否经常打电话给它,以至于它成为一个问题。@Alois Kraus谢谢你的建议,我这么做了,看看我的答案。我只想指出,在抽象中询问性能通常是没有意义的。您需要为系统设置性能目标,然后编写简单、易懂(且正确)的代码。然后衡量绩效并决定其是否达到目标。如果它符合目标且易于理解,那么不要仅仅为了“性能”而将其改写为不易理解(并且可能不太正确)。