如何编写可中止的同步方法?
Posted
技术标签:
【中文标题】如何编写可中止的同步方法?【英文标题】:How to write an abort-able synchronous method? 【发布时间】:2011-06-26 11:09:01 【问题描述】:我需要同步运行一个方法列表,并能够停止执行列表。在执行之前使用重置事件很容易停止循环(参见Execute
中的第一行)。
如何同时等待action.Execute()
和action.Execute()
的回复?
private ManualResetEvent _abortingToken = new ManualResetEvent(false);
private List<IAction> _actions;
public void Abort()
_abortingToken.Set();
public void Execute()
foreach (var action in _actions)
if (_abortingToken.WaitOne(0))
break; // Execution aborted.
action.Execute(); // Somehow, I need to call this without blocking
while (/*Execute not finished*/)
if (_abortingToken.WaitOne(1))
action.Abort();
我认为使用 Tasks 很容易执行,但不幸的是我使用的是 .net 3.5。
编辑:受SLaks answer启发的解决方案:
public void Execute()
Action execute = null;
IAsyncResult result = null;
foreach (var action in _actions)
execute = new Action(scriptCommand.Execute);
if (_abortingToken.WaitOne(0))
break; // Execution aborted.
result = execute.BeginInvoke(null, null);
while (!result.IsCompleted)
if (_abortingToken.WaitOne(10))
action.Abort();
break;
execute.EndInvoke(result);
【问题讨论】:
【参考方案1】:这与同步性相反。 您需要在后台线程上运行该方法。
例如,您可以使用Delegate.BeginInvoke
调用该方法,然后检查IAsyncResult.IsCompleted
。 (并确保之后致电EndInvoke
)
【讨论】:
谢谢。使用BeginInvoke
可以创建一个非常优雅的代码,而不会产生很多开销。但是我必须打电话给EndInvoke
吗? EndInvoke
的唯一目的不是检索返回值或异常吗?如果我不关心结果(即中止后)怎么办?
@HuBeZa:如果你不调用EndInvoke
,你会泄漏内存。【参考方案2】:
您可以在另一个线程中运行 Execute,然后您的 while 尝试超时加入。
public void Execute()
foreach (var action in _actions)
if (_abortingToken.WaitOne(0))
break; // Execution aborted.
var workThread = new Thread(action.Execute);
workThread.Start();
while (!workThread.Join(100)) /Milliseconds, there is also a timespan overload
if (_abortingToken.WaitOne(1))
action.Abort();
见http://msdn.microsoft.com/en-us/library/system.threading.thread_methods.aspx。
【讨论】:
以上是关于如何编写可中止的同步方法?的主要内容,如果未能解决你的问题,请参考以下文章