【问题标题】: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);
    }
}

【问题讨论】:

    标签: c# multithreading .net-3.5 asynchronous


    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-17
      • 1970-01-01
      • 2019-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-28
      • 1970-01-01
      相关资源
      最近更新 更多