1

我有一个场景,我需要拆分一个线程来工作。如果我得到一个不好的结果,但我的代码将继续正常。我真的需要知道处理是否超过了我预定的超时时间。我有一个看起来很像的 Future 实现。我绑定到 .NET 3.5,所以我没有能力使用 4.0 中引入的那些似乎使它容易工作的东西。

我有一个看起来很像的 Future 实现:

public class Future<T> {
        public delegate R FutureDelegate<R>();
        public Future (FutureDelegate<T> del) {
                Del = del;
                Result = del.BeginInvoke(null,null);
        }
        private FutureDelegate<T> Del;
        private IAsyncResult Result;
        private T PValue;
        private bool HasValue = false;
        private T Value {
                get {
                        if (!HasValue) {
                                if (!Result.IsCompleted)
                                        Result.AsyncWaitHandle.WaitOne();
                                PValue = Del.EndInvoke(Result);
                                HasValue = true;
                        }
                        return PValue;
                }
        }
        public static implicit operator T(Future<T> f) {
                return f.Value;
        }
}

我没有编写此代码,但它似乎来自我在尝试解决此问题时发现的博客。第一个直觉是添加一个布尔TimedOut标志,我可以在 WaitOne 之后检查,例如:

            if (!Result.AsyncWaitHandle.WaitOne(timeout_ms))
            {
                HasTimedOut = true;
                HasValue = false;
            }
            else
            {
                HasTimedOut = false;
                HasValue = true;
            }

但是,我写了一个测试来检查这个,它似乎总是在超时的情况下失败......总是将 HasTimedOut 返回为假。如果我制作测试用例,它应该返回 true:

var aFuture = new Future<int>(delegate {Sleep(5)l return 1+1;}, 1);
Assert.IsTrue(aFuture.HasTimedOut);

这当然是除非我在这里做出假设的飞跃。我有什么误解吗?为客户班级获得此反馈的最佳方式是什么?我也尝试抛出异常,但我大概只是​​杀死了当前的控制流,并没有将任何有意义的东西返回给客户端代码。

4

1 回答 1

0

移动一些实现细节使我能够达到预期的结果。见下文:

    public Future(FutureDelegate<T> del, int timeout_ms)
    {
        Del = del;
        Result = del.BeginInvoke(null, null);

        if (!Result.IsCompleted)
        {
            if (!Result.AsyncWaitHandle.WaitOne(timeout_ms))
            {
                HasTimedOut = true;
            }
            else
            {
                HasTimedOut = false;
            }
        }

        PValue = Del.EndInvoke(Result);             
    }

将代码推入构造函数允许抛出异常或设置 HasTimedOut 标志并将其持久化,直到我需要它为止。

于 2013-08-06T21:57:43.897 回答