如何编写可中止的同步方法?

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。

【讨论】:

以上是关于如何编写可中止的同步方法?的主要内容,如果未能解决你的问题,请参考以下文章

java多线程有几种实现方法?线程之间如何同步

如何将方法调用与 alsa 播放同步?

同步方法或同步块:在java中编写单例类时哪一个更好? [重复]

如何从同步方法调用中回调而不等待它?

编写帖子并将其与1000个站点自动同步的最快方式

windows 服务器时间同步失败处理方法