2

我正在WaitHandle为负责在内部创建资源的对象公开一个接口,但这可能需要很长时间。合同如下所示:

public interface IHaveExpensiveResources {
    WaitHandle FinishedInitialization { get; }
}

WaitHandle开始未设置,但我在初始化完成后设置它(在后台,在构造函数返回后)。我不喜欢这个的事情是这个合同的消费者可以设置WaitHandle自己,当他们没有业务能够做到这一点时。它让我想起了 get-onlyIList<T>属性和IReadOnlyList<T>.

C# 中是否有像 a 那样WaitOnlyWaitHandle只公开WaitOne()重载方法的东西?

所以我不是 XY 问题的受害者,是否有更规范的异步构造对象的方法来构建具有较长构造时间的对象?

4

2 回答 2

4

您是否必须传回 aWaitHandle或者您是否可以制作自己的包装类,只公开您想要的功能,类似于 ReadOnlyCollection 所做的?

一种选择是将 WaitHandle 包装到一个任务中(取自MSDN 的代码示例)

public static Task WaitOneAsync(this WaitHandle waitHandle)
{
    if (waitHandle == null) 
        throw new ArgumentNullException("waitHandle");

    var tcs = new TaskCompletionSource<bool>();
    var rwh = ThreadPool.RegisterWaitForSingleObject(waitHandle, 
        delegate { tcs.TrySetResult(true); }, null, -1, true);
    var t = tcs.Task;
    t.ContinueWith( (antecedent) => rwh.Unregister(null));
    return t;
}

然后你只需调用.WaitOneAsync()任何FinishedInitialization会返回的东西并返回它Task

于 2016-05-27T18:30:47.223 回答
3

为了完整起见,这是我创建的用于公开WaitOne()重载方法的接口和实现WaitHandle

public interface IWaitOnlyWaitHandle
{
    bool WaitOne();
    bool WaitOne(TimeSpan timeout);
    bool WaitOne(int millisecondsTimeout);
    bool WaitOne(int millisecondsTimeout, bool exitContext);
    bool WaitOne(TimeSpan timeout, bool exitContext);
}

public sealed class WaitOnlyWaitHandle : IWaitOnlyWaitHandle
{
    # UPDATE: this object does not own the passed in WaitHandle
    private readonly WaitHandle _waitHandle;
    public WaitOnlyWaitHandle(WaitHandle waitHandle)
    {
        _waitHandle = waitHandle;
    }

    public bool WaitOne() => _waitHandle.WaitOne();
    public bool WaitOne(TimeSpan timeout) => _waitHandle.WaitOne(timeout);
    public bool WaitOne(int millisecondsTimeout) => _waitHandle.WaitOne(millisecondsTimeout);
    public bool WaitOne(int millisecondsTimeout, bool exitContext) => _waitHandle.WaitOne(millisecondsTimeout, exitContext);
    public bool WaitOne(TimeSpan timeout, bool exitContext) => _waitHandle.WaitOne(timeout, exitContext);
}

更新:根据@stevenbone 的评论,此实现不拥有WaitHandle传递给构造函数的生命周期。阅读他的评论以获取更多信息。

于 2016-05-27T18:43:51.220 回答