SynchronizationContext.Send to call Func returning the result

In the current project, I have a simple component that can be removed from the visual studio toolbar in Forms and UserControls in the WinForms application.

It worked just fine as it is - and just wraps the SynchronizationContext submission and publishing methods captured during ISupportInitialize.BeginInit (UI context for form / control ownership).

Here is the existing code for the component in it the simplest form.

public class SyncContextComponent : Component, ISupportInitialize
{
    private SynchronizationContext _context;

    public SyncContextComponent() { }
    public SyncContextComponent(IContainer container)
    {
        container.Add(this);
    }

    void ISupportInitialize.BeginInit()
    {
        _context = SynchronizationContext.Current; // context of creator
    }
    void ISupportInitialize.EndInit() { }

    /// <summary>
    /// Dispatches an <b>asynchronous</b> message to <see cref="Context"/>
    /// </summary>
    /// <param name="action">The delegate to call</param>
    /// <example>
    /// uiContext.Post(() => this.WorkOnUiControls());
    /// </example>
    public void Post(Action action)
    {
        _context.Post(new SendOrPostCallback(_ => action()), null);
    }

    /// <summary>
    /// Dispatches an <b>synchronous</b> message to <see cref="Context"/>
    /// </summary>
    /// <param name="action">The delegate to call</param>
    /// <example>
    /// uiContext.Send(() => this.WorkOnUiControls());
    /// </example>
    public void Send(Action action)
    {
        _context.Send(new SendOrPostCallback(_ => action()), null);
    }
}

I now needed to expand this to support return values, and was considering various ways ...

I am interested in understanding the implications of the following three ways to solve this problem, and if there is a “better” way.

: , , - , 1 arg1 TResult, .. Func<T1, TResult>. , , , Func<TResult> , , 9args Func<T1,T2....T9,TResult>, Action.

Send0: - , :

    public TResult Send0<T1, TResult>(Func<T1, TResult> func, T1 arg1)
    {
        TResult retval = default(TResult);
        _context.Send(new SendOrPostCallback((x) =>
        {
            retval = func(arg1);
        })
        , null);
        return retval;
    }

Send1: - stackoverflow, , , , , state arg. , - , , , :

    private class SendFuncState1<T1, TResult>
    {
        public TResult Result { get; set; }
        public T1 Arg1 { get; set; }
    }
    public TResult Send1<T1, TResult>(Func<T1, TResult> func, T1 arg1)
    {
        SendFuncState1<T1, TResult> state = new SendFuncState1<T1, TResult>()
        {
            Arg1 = arg1
        };
        _context.Send(new SendOrPostCallback((x) =>
        {
            var state0 = (SendFuncState1<T1, TResult>)x;
            state0.Result = func(state0.Arg1);
        })
        , state);
        return state.Result;
    }

Send2: - , , , , Func? - :

    private class SendFuncState2<T1, TResult>
    {
        public Func<T1, TResult> Func { get; set; }
        public TResult Result { get; set; }
        public T1 Arg1 { get; set; }
    }
    public TResult Send2<T1, TResult>(Func<T1, TResult> func,
        T1 arg1)
    {
        SendFuncState2<T1, TResult> state = new SendFuncState2<T1, TResult>()
        {
            Func = func,
            Arg1 = arg1
        };
        _context.Send(new SendOrPostCallback((x) =>
        {
            var state0 = (SendFuncState2<T1, TResult>)x;
            state0.Result = state0.Func(state0.Arg1);
        })
        , state);
        return state.Result;
    }

, , WinForms, 10k ( ) ​​ . , /.

So - is Send0 fine - / ? - - ?

+4
1

, . - . ( ). Lambdas CLR. , .

, Windows Message , , . .

+2

Source: https://habr.com/ru/post/1607551/


All Articles