0

バックグラウンド ワーカー プロセスで何らかの作業を行おうとしていますが、作業が完了している間にモーダル ダイアログを表示したいと考えています。単純な Action デリゲートのコードはうまく機能していますが、Func デリゲートを渡して戻り値の型を取得できるようにしたいと考えています。私がこれまでに持っているのは、メソッドを持つフォームです

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

次に働きたいのは次のようなものです

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

        return (TResult)Result;
    }

_workWithReturn の型を宣言するときに転倒し続けるため、これまでのところ運がありませんでした

        Func<TResult> _workWithReturn;

誰か考えがありますか?

これが完全なコードです。

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 ShowDialogWhile<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();
    }

}
4

3 に答える 3

2

コンパイル時に発生するエラーは、Compact フレームワークとは関係ありませんが、Generics の不適切な使用が原因です。他の人が言ったように、クラス自体で宣言しない限り、タイプ TResult はクラスの範囲外です。

あなたが達成しようとしていることを見ると、メソッドに固有のすべてのタイプをローカルに保つことで、必要なものを得ることができると言えます。次のように変更します。

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;
    }
}

あなたの「作業」は、関数を呼び出す匿名デリゲートによって実行され、関数の戻りは ShowDialogWhile 関数のスコープ内に保持されます。素敵で簡単なトリック。

そこにリファクタリングを投入するだけで、既存のメソッドを使用してワーカーとダイアログ ロジックを処理できます。

    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        var result = default(TResult);
        ShowDialogWhile(() =>
        {
            result = work();
        });
        return result;
    }
于 2011-06-17T06:50:36.213 に答える
1

TResult を使用したジェネリック メソッドがありますが、その型を使用するフィールドもあります。実行時にそのタイプのフィールドが必要な場合は、ジェネリック定義をメソッドからクラスに移動します。

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 { ... }
于 2011-06-16T18:33:25.403 に答える
1

あなたの問題は、メソッドでTResult定義されたジェネリックですが、その範囲外で宣言したことです。1 つの修正は、代わりにクラス宣言の一部として持つことです。ShowDialogWhile_workWithReturnTResult

于 2011-06-16T18:33:40.533 に答える