gpt4 book ai didi

c# - ExecutionContext.Capture() 和 ExecutionContext.Run(context, work, state) 的成本

转载 作者:太空狗 更新时间:2023-10-29 21:56:58 26 4
gpt4 key购买 nike

有人知道 ExecutionContext.Capture()ExecutionContext.Run(context, work, state) 是否很昂贵吗?

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

我问是因为我有一个 ContextItem,我在其中保存上下文工作和状态以供稍后执行。因为我希望能够对执行工作时可能抛出的异常使用react,所以我有一个回退,如果在工作中抛出异常则执行。而且我还有最后的工作,无论是否抛出异常,在任何情况下都会执行。因为我只能使用 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; }
}
}

结果是:

enter image description here

因此,如果我做对了,捕获和执行队列的平均成本是锁定的 5 倍。

同时回答我的问题部分:

Or does this sound like a totally wrong approach?

我读入了this article那个

if you have to know they’re there, either you’re doing something super advanced, or something’s gone wrong.

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

关于c# - ExecutionContext.Capture() 和 ExecutionContext.Run(context, work, state) 的成本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34687336/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com