1. ホーム
  2. c#

[解決済み] インターフェース実装の非同期化

2022-05-06 18:31:39

質問

私は現在、いくつかの非同期メソッドを使用してアプリケーションを作成しようとしています。 私のすべてのIOは、インターフェイスの明示的な実装を通して行われ、私は操作を非同期にする方法について少し混乱しています。

私の見るところ、実装には2つの選択肢があります。

interface IIO
{
    void DoOperation();
}

OPTION1: 暗黙の実装を非同期で行い、その結果を暗黙の実装で待ちます。

class IOImplementation : IIO
{

     async void DoOperation()
    {
        await Task.Factory.StartNew(() =>
            {
                //WRITING A FILE OR SOME SUCH THINGAMAGIG
            });
    }

    #region IIO Members

    void IIO.DoOperation()
    {
        DoOperation();
    }

    #endregion
}

OPTION2: 明示的な実装を非同期で行い、暗黙的な実装からタスクを待ち受ける。

class IOAsyncImplementation : IIO
{
    private Task DoOperationAsync()
    {
        return new Task(() =>
            {
                //DO ALL THE HEAVY LIFTING!!!
            });
    }

    #region IIOAsync Members

    async void IIO.DoOperation()
    {
        await DoOperationAsync();
    }

    #endregion
}

これらの実装のうち、どちらかが優れているのか、それとも私が考えていない別の方法があるのでしょうか?

どのように解決するのですか?

どちらの選択肢も正しくありません。あなたは同期インターフェースを非同期に実装しようとしています。そんなことはしないでください。問題は DoOperation() が返ってきても、まだ操作は完了していません。さらに悪いことに、もし操作の途中で例外が発生したら(IO操作ではよくあることです)、ユーザーはその例外に対処する機会がありません。

そのために必要なのは インターフェイスを変更する のように、非同期で実行されます。

interface IIO
{
    Task DoOperationAsync(); // note: no async here
}

class IOImplementation : IIO
{
    public async Task DoOperationAsync()
    {
        // perform the operation here
    }
}

こうすることで、ユーザーはその操作が async となり、彼らは await となります。これはまた、あなたのコードのユーザーをかなり強制的に async しかし、それはやむを得ないことです。

また StartNew() の実装はあくまで例であり、非同期IOの実装にそれは必要ないはずです。(そして new Task() はさらに悪いことに、それは動作さえしません。 Start() その Task .)