Non-blocking wait without TPL in 3.5

2019-09-15 06:04发布

问题:

How can I perform wait without blocking thread and without TPL' ContinueWith? For ex. in 3.5? I know about TPL's ported version for 3.5 (by RX team), but i'm curious to know - which threading primitives I can use for that (... what is behing the scenes of TPL). And what ContinueWith alternatives in TPL?

// will this handler block thread during async IO operation?

public class AsyncHandler : IHttpAsyncHandler
    {
        public void ProcessRequest(HttpContext ctx)
        {
            // not used
        }

    public bool IsReusable
    {
        get { return false; }
    }

    public IAsyncResult BeginProcessRequest(HttpContext ctx,
                                            AsyncCallback cb,
                                            object obj)
    {
        AsyncRequestState reqState =
                            new AsyncRequestState(ctx, cb, obj);
        AsyncRequest ar = new AsyncRequest(reqState);
        ThreadStart ts = new ThreadStart(ar.ProcessRequest);
        Thread t = new Thread(ts);
        t.Start();

        return reqState;
    }

    public void EndProcessRequest(IAsyncResult ar)
    {
        AsyncRequestState ars = ar as AsyncRequestState;
        if (ars != null)
        {
            // Some cleanup
        }
    }
}
class AsyncRequestState : IAsyncResult
{
    public AsyncRequestState(HttpContext ctx,
                                AsyncCallback cb,
                                object extraData)
    {
        _ctx = ctx;
        _cb = cb;
        _extraData = extraData;
    }

    internal HttpContext _ctx;
    internal AsyncCallback _cb;
    internal object _extraData;
    private bool _isCompleted = false;
    private ManualResetEvent _callCompleteEvent = null;

    internal void CompleteRequest()
    {
        _isCompleted = true;
        lock (this)
        {
            if (_callCompleteEvent != null)
                _callCompleteEvent.Set();
        }           
        if (_cb != null)
            _cb(this);
    }

    public object AsyncState
    { get { return (_extraData); } }
    public bool CompletedSynchronously
    { get { return (false); } }
    public bool IsCompleted
    { get { return (_isCompleted); } }
    public WaitHandle AsyncWaitHandle
    {
        get
        {
            lock (this)
            {
                if (_callCompleteEvent == null)
                    _callCompleteEvent = new ManualResetEvent(false);

                return _callCompleteEvent;
            }
        }
    }
}

class AsyncRequest
{
    private AsyncRequestState _asyncRequestState;

    public AsyncRequest(AsyncRequestState ars)
    {
        _asyncRequestState = ars;
    }

    public void ProcessRequest()
    {
        //calling webservice or executing sql command asynchronously
        AsyncIOOperationWithCallback(state =>
                                        {
                                            ((AsyncRequestState)state.Context)._ctx.Response.Write("Operation completed");
                                            _asyncRequestState.CompleteRequest();
                                        }, _asyncRequestState);

    }
}

回答1:

Wait, by definition, is "blocking". You can wait on another thread, but you'd be blocking that thread. If by "non-blocking" you mean not blocking the UI, then you can wait on another thread and notify the UI thread via an event (which would handle InvokeRequired/BeginInvoke if necessary).

If that's not what you're asking, please provide more detail.



回答2:

The way you typically deal with an asynchronous operation without blocking a thread is to have your asynchronous operation support a callback. The TPL really doesn't do anything magic here; if the underlying operations don't support some form of callback at some point, you're still stuck with something blocking eventually. The classic 'Begin/End' Asynchronous Programming Model handles this requirement perfectly fine.

When the TPL really shines is in providing better support for exception handling/aggregation and allowing more complex continuation models (such as ContinueWhenAll or ContinueWhenAny.) There is also new support for cancellation, including prevention of subsequent continuation. Continuation itself, though, is really nothing more than a callback in a fancier, cleaner package.