显然,我不了解如何使用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中逐行调试,它会被调用。)
在我的ASP.NET Web API控制器/ Ajax POST中调用此方法。
我在这里做错了什么?
答案 0 :(得分: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;
}
}
答案 1 :(得分:2)
未设置变量的原因是:
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.";
}
}
免责声明:我实际上没有执行上述代码;我只是写它来说明应该做什么。
答案 2 :(得分:1)
您应该从方法返回Task<T>
类型,在这种情况下它将是Task<string>
。
答案 3 :(得分:0)
您正在使用异步操作。如果您想等待其完成,则必须使用Wait
方法,否则执行任务:
task.ContinueWith(o =>
{
//File name
filename = provider.BodyPartFileNames.First().Value;
).Wait();
return filename;
修改强> 一些异步方法在创建任务后立即启动任务,而其他方法则要求您明确启动它们。您必须查阅每个文档以确定。在这种情况下,任务似乎会自动启动。