5

どうやら、ContinueWith メソッドの使用方法を理解していないようです。私の目標は、タスクを実行し、完了したらメッセージを返すことです。

これが私のコードです:

    public string UploadFile()
    {
        if (Request.Content.IsMimeMultipartContent())
        {
            //Save file
            MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("~/Files"));
            Task<IEnumerable<HttpContent>> task = Request.Content.ReadAsMultipartAsync(provider);

            string filename = "Not set";

            task.ContinueWith(o =>
            {
                //File name
                filename = provider.BodyPartFileNames.First().Value;
            }, TaskScheduler.FromCurrentSynchronizationContext()); 

            return filename;
        }
        else
        {
            return "Invalid.";
        }
    }

変数 "filename" は常に "Not set" を返します。ContinueWith メソッド内のコードが呼び出されないようです。(VSで1行ずつデバッグすると呼び出されます。)

このメソッドは、ASP.NET Web API コントローラー/Ajax POST で呼び出されています。

ここで何が間違っていますか?

4

4 に答える 4

7

非同期操作を使用している場合、操作を非同期にするのが最善の方法です。そうしないと、作成している非同期呼び出しの利点が失われます。メソッドを次のように書き直してみてください。

public Task<string> UploadFile()
{
    if (Request.Content.IsMimeMultipartContent())
    {
        //Save file
        MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("~/Files"));
        Task<IEnumerable<HttpContent>> task = Request.Content.ReadAsMultipartAsync(provider);

        return task.ContinueWith<string>(contents =>
        {
            return provider.BodyPartFileNames.First().Value;
        }, TaskScheduler.FromCurrentSynchronizationContext()); 
    }
    else
    {
        // For returning non-async stuff, use a TaskCompletionSource to avoid thread switches
        TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
        tcs.SetResult("Invalid.");
        return tcs.Task;
    }
}
于 2012-05-08T21:16:02.167 に答える
2

変数が設定されていない理由は次のとおりです。

  • タスクはインスタンス化されますが、実行されません。
  • タスクが実行されたとしても、実行が完了する前に関数が返される可能性があるため、「設定されていません」が返されます。これに対する修正は、最後のタスク (1 つの設定fileName) が完了するのを待っています。

コードは次のように修正できます。

public string UploadFile()
{
    if (Request.Content.IsMimeMultipartContent())
    {
        //Save file
        MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("~/Files"));
        Task<IEnumerable<HttpContent>> task = Request.Content.ReadAsMultipartAsync(provider);

        string filename = "Not set";

        var finalTask = task.ContinueWith(o =>
            {
                //File name
                filename = provider.BodyPartFileNames.First().Value;
            }, TaskScheduler.FromCurrentSynchronizationContext()); 

        task.Start();

        finalTask.Wait();

        return filename;
    }
    else
    {
        return "Invalid.";
    }
}

追加は次のとおりです。

  • の戻り値task.ContinueWithを という変数に代入しましたfinalTask。このタスクが必要なのは、完了するのを待つためです
  • タスク(task.Start();ライン)を開始しました
  • 戻る前に最後のタスクが完了するのを待った ( finalTask.Wait();)

可能であれば、これを非同期に実装しないことを検討してください。最終的には同期であり (終了するのを待っています)、現在の実装ではおそらく回避できる複雑さが追加されます。

これらの行に沿って何かをすることを検討してください(可能であれば):

public string UploadFile()
{
    if (Request.Content.IsMimeMultipartContent())
    {
        //Save file
        MultipartFormDataStreamProvider provider = new MultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("~/Files"));

        Request.Content.ReadAsMultipart(provider); // don't know if this is really valid.

        return provider.BodyPartFileNames.First().Value;
    }
    else
    {
        return "Invalid.";
    }
}

免責事項:上記のコードを実際に実行したことはありません。何をすべきかを説明するために書いただけです。

于 2012-05-08T16:36:46.147 に答える
1

メソッドから型を返す必要があります。Task<T>この場合は。になりますTask<string>

于 2012-05-08T16:19:19.913 に答える
0

非同期操作を使用しています。完了するのを待ちたいWait場合は、タスクの別の方法を使用する必要があります。

task.ContinueWith(o =>
        {
            //File name
            filename = provider.BodyPartFileNames.First().Value;
        ).Wait();

return filename;

編集: 非同期メソッドの中には、作成されるとすぐにタスクを開始するものもあれば、明示的に開始するように求めるものもあります。確認するには、それぞれのドキュメントを参照する必要があります。この場合、タスクは自動的に開始されるようです。

于 2012-05-08T16:20:14.910 に答える