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谢谢你的建议,我这么做了,看看我的答案。我只想指出,在抽象中询问性能通常是没有意义的。您需要为系统设置性能目标,然后编写简单、易懂(且正确)的代码。然后衡量绩效并决定其是否达到目标。如果它符合目标且易于理解,那么不要仅仅为了“性能”而将其改写为不易理解(并且可能不太正确)。