0

私はコールバックと非同期関数を使用するのが初めてなので、これにアプローチする最善の方法が少しわかりません。

SendPhoto()GUI によって呼び出される関数を作成しました。関数は、SendPhoto()私の GUI とは別のクラスにあります。

    public string SendPhoto(string filename)
    {
        byte[] response = PostFile(_url, filename);

        String responsestring = Encoding.ASCII.GetString(response);

        if (responsestring.StartsWith("ERROR:"))
            return responsestring;
        else if (responsestring.Contains("<valid>1</valid>"))
            return "OK";
        else
            return responsestring;
    }

私のPostFile()関数は を呼び出しWebClient.UploadFile()ていましたが、応答は に返されSendPhoto()、うまく機能しました。次に、写真を非同期で送信することにしたので、PostFile()関数で呼び出しを から に変更しUploadfile()ましたUploadFileAsync()

ただし、UploadFileAsync()値が返されないことに気付きました。アップロードが完了したら、 UploadFileCompletedEventHandler を使用して応答を取得する必要があります。SendPhoto()そこで、レスポンスを取得するためにand と同じクラスにコールバック関数をPostFile()記述し、その関数で UploadFileCompletedEventHandler をインスタンス化し、関数に渡しましたPostFile()

問題は、応答を関数に戻す方法がわからないため、SendPhoto()関数が応答を解釈してフレンドリーな応答を GUI に返すことができることです。以前は、すべてが同期していたとき、応答はスタックに戻されただけでしたが、現在は、応答はいくつかのレイヤーが削除されて返されます。

コールバック関数から への応答を取得する最良の方法は何SendPhoto()ですかPostFile()? イベント ハンドラのコールバックを GUI に移動し、UploadFileCompletedEventHandlertoを渡すSendPhoto()ことを考えましたPostFile()。しかし、私は「ビジネス ロジック」(つまり、応答の解釈) を GUI クラスから除外しようとしています。

4

1 に答える 1

1

わかりました、今朝はさらに作業を進め、「await」を使用して非常に洗練された解決策を見つけました (ありがとう、Muctadir Dinar!)。「await」キーワードをサポートするために、UploadFileTaskAsync() への呼び出しを変更する必要があり、すべてのメソッドを「async」で装飾し、GUI のボタンまでずっとタスクを返すようにする必要がありました。イベントハンドラーをクリックしますが、完了したらうまくいきました! これは .NET Framework 4.5 でのみ機能すると思います。

    private async void UploadPhotoButton_Click(object sender, EventArgs e)
    {
        ...
        string theResult = await MyProvider.SendPhotoAsync(pathToFile, new UploadProgressChangedEventHandler(UploadProgressCallback));
        OutputBox.Text = theResult;
    }

    public async Task<string> SendPhotoAsync(string filename, UploadProgressChangedEventHandler changedHandler)
    {
        byte[] response = await PostFileAsync(_url, filename, changedHandler);

        String responsestring = Encoding.ASCII.GetString(response);

        if (responsestring.StartsWith("ERROR:"))
            return responsestring;
        else if (responsestring.Contains("<valid>1</valid>"))
            return "OK";
        else
            return responsestring;
    }

    async Task<byte[]> PostFileAsync(string uri, string filename, UploadProgressChangedEventHandler changedHandler)
    {
        byte[] response = null;
        using (WebClient client = new WebClient())
        {
            client.Headers = GetAuthenticationHeader();
            client.UploadProgressChanged += changedHandler;

            response = await client.UploadFileTaskAsync(new Uri(uri), filename);
        }

        return response;
    }
于 2013-09-26T15:56:54.680 に答える