开发者

Compact Framework Func<T> issues

I am trying to do some work on a backgroundworker process and while the work is done I want to display a modal dialog. I have got the code working nicely for a simple Action delegate but want to be able to pass in a Func delegate and get a return type. What I have so far is a Form with a method

    public void ShowDialogWhile(Action work)
    {
        _work = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();
    }

What I'd like to get working next is something like

    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        _workWithReturn = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();

        return (TResult)Result;
    }

I haven't had any luck so far because I keep falling over when declaring the type of my _workWithReturn

        Func<TResult> _workWithReturn;

Does anyone have any thoughts?

Here is the full code.

public partial class AsyncWaitDialog : Form, IAsyncDialog
{
    BackgroundWorker _worker = new BackgroundWorker();
    Action _work;
    Func<TResult> _workWithReturn;
    public object Result { get; private set; }


    public AsyncWaitDialog()
    {
        InitializeComponent();
        _worker.DoWork += HandleDoWorkEvent;
        _worker.RunWorkerCompleted += HandleWorkerCompleted;
    }


    public void ShowDialogWhile(Action work)
    {
        _work = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();
    }

    public TResult Show开发者_如何学PythonDialogWhile<TResult>(Func<TResult> work)
    {
        _workWithReturn = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();

        return (TResult)Result;
    }


    private void HandleDoWorkEvent(object sender, EventArgs e)
    {
        try
        {
            if (_work != null)
            {
                _work();
            }
            if (_workWithReturn != null)
            {
                Result = _workWithReturn();
            }

        }
        catch (Exception)
        {
            this.Close();
            throw;
        }
    }

    private void HandleWorkerCompleted(object sender, EventArgs e)
    {
        this.Close();
    }

}


The errors you are receiving when compiling are not anything to do with Compact framework, but rather the incorrect use of Generics. As others have said, the type TResult is out of scope in your class unless you declare it on the class itself.

If I look at what you are trying to achieve I would say that you could get what you are wanting through keeping everything type specific local to the method. Make changes as follows:

public partial class AsyncWaitDialog : Form, IAsyncDialog
{
    ...
    //Func<TResult> _workWithReturn; REMOVE THIS LINE
    ...

    //Change your function to be this:
    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        var result = default(TResult);
        _work = () =>
        {
            result = work();
        };
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();

        return result;
    }
}

Your 'work' is now being performed by an anonymous delegate which calls your function and the return of the function is held within the scope of the ShowDialogWhile function. Nice and easy trick.

Just to throw a refactoring in there, you could use your existing method to handle the worker and dialog logic:

    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        var result = default(TResult);
        ShowDialogWhile(() =>
        {
            result = work();
        });
        return result;
    }


You have a generic method with TResult, but you also have a field using the type. Move the generic definition from the method to the class if you need a field of that type at runtime.

public partial class AsyncWaitDialog : Form, IAsyncDialog
{
    ...
    Func<TResult> _workWithReturn; //TRESULT IS NOT IN SCOPE
    ...

    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        //TResult **IS** in scope here
        _workWithReturn = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();

        return (TResult)Result;
    }


// possible solution, move the generic definition of TResult to the class definition

public partial class AsyncWaitDialog<TResult> : Form, IAsyncDialog { ... }


Your problem is that TResult is a generic defined on the ShowDialogWhile method, but you've declared your _workWithReturn out of that scope. One fix would be to have TResult as part of the class declaration instead.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜