我不太明白之间的差别Task.Wait和await.
我在ASP.NET WebAPI服务中有类似于以下函数:
public class TestController : ApiController
{
public static async Task<string> Foo()
{
await Task.Delay(1).ConfigureAwait(false);
return "";
}
public async static Task<string> Bar()
{
return await Foo();
}
public async static Task<string> Ros()
{
return await Bar();
}
// GET api/test
public IEnumerable<string> Get()
{
Task.WaitAll(Enumerable.Range(0, 10).Select(x => Ros()).ToArray());
return new string[] { "value1", "value2" }; // This will never execute
}
}
Run Code Online (Sandbox Code Playgroud)
哪里Get会僵局.
什么可能导致这个?当我使用阻塞等待而不是await Task.Delay?时,为什么这不会导致问题?
我想触发一个在后台线程上运行的任务.我不想等待任务完成.
在.net 3.5中,我会这样做:
ThreadPool.QueueUserWorkItem(d => { DoSomething(); });
Run Code Online (Sandbox Code Playgroud)
在.net 4中,TPL是建议的方式.我见过的常见模式是:
Task.Factory.StartNew(() => { DoSomething(); });
Run Code Online (Sandbox Code Playgroud)
但是,该StartNew()方法返回一个Task实现的对象IDisposable.推荐这种模式的人似乎忽视了这一点.有关该Task.Dispose()方法的MSDN文档说:
"在释放对任务的最后一个引用之前,始终调用Dispose."
你不能在任务完成之前调用dispose,所以让主线程等待并调用dispose会首先打破后台线程上的操作.似乎也没有任何已完成/已完成的事件可用于清理.
Task类上的MSDN页面没有对此进行评论,并且"Pro C#2010 ..."一书推荐了相同的模式,并且没有对任务处理做出评论.
我知道如果我离开它,终结者最终会抓住它,但当我做了大量的火灾并且忘记了这样的任务并且终结者线程被淹没时,它会回来咬我吗?
所以我的问题是:
Dispose()就Task在这种情况下类?如果是这样,为什么会有风险/后果?Task我错过的物体?请考虑以下Windows窗体代码:
private async void UpdateUIControlClicked(object sender, EventArgs e)
{
this.txtUIControl.Text = "I will be updated after 2nd await - i hope!";
await Task.Delay(5000).ConfigureAwait(continueOnCapturedContext: false);
this.txtUIControl.Text = "I am updated now.";
}
Run Code Online (Sandbox Code Playgroud)
这里异常是在第3行引发的,因为在等待代码在非UI线程上执行之后.ConfigureAwait(false)有用吗?
说我有两个场景:
1)WebApi控制器
[System.Web.Http.HttpPost]
[System.Web.Http.AllowAnonymous]
[Route("api/registerMobile")]
public async Task<HttpResponseMessage> RegisterMobile(RegisterModel model)
{
var registerResponse = await AuthUtilities.RegisterUserAsync(model, _userService, User);
if (registerResponse.Success) {
var response = await _userService.GetAuthViewModelAsync(model.Username, User);
return Request.CreateResponse(HttpStatusCode.OK, new ApiResponseDto() { Success = true, Data = response });
}
else {
return Request.CreateResponse(HttpStatusCode.OK, registerResponse);
}
}
Run Code Online (Sandbox Code Playgroud)
2)MVC控制器
[Route("public")]
public async Task<ActionResult> Public()
{
if (User.Identity.IsAuthenticated)
{
var model = await _userService.GetAuthViewModelAsync(User.Identity.Name);
return View("~/Views/Home/Index.cshtml", model);
}
else
{
var model = await _userService.GetAuthViewModelAsync(null);
return View("~/Views/Home/Index.cshtml", model);
}
}
Run Code Online (Sandbox Code Playgroud)
我一直在阅读我应该使用的时间ConfigureAwait …
ConfigureAwait(false)在C#中使用await/async 时,有很多指南可供使用.
似乎一般的建议是ConfigureAwait(false)在库代码中使用,因为它很少依赖于同步上下文.
但是,假设我们正在编写一些非常通用的实用程序代码,它将函数作为输入.一个简单的例子可能是以下(不完整的)功能组合器,以简化基于任务的简单操作:
地图:
public static async Task<TResult> Map<T, TResult>(this Task<T> task, Func<T, TResult> mapping)
{
return mapping(await task);
}
Run Code Online (Sandbox Code Playgroud)
FlatMap:
public static async Task<TResult> FlatMap<T, TResult>(this Task<T> task, Func<T, Task<TResult>> mapping)
{
return await mapping(await task);
}
Run Code Online (Sandbox Code Playgroud)
问题是,我们应该ConfigureAwait(false)在这种情况下使用吗?我不确定上下文捕获是如何工作的.关闭.
一方面,如果组合器以功能方式使用,则不需要同步上下文.另一方面,人们可能会滥用API,并在提供的函数中执行依赖于上下文的内容.
一种选择是为每个场景(Map和/ MapWithContextCapture或某些东西)设置单独的方法,但感觉很难看.
另一种选择可能是将map/flatmap选项添加到a中ConfiguredTaskAwaitable<T>,但是由于等待不必实现接口,这会导致大量冗余代码,在我看来更糟糕.
是否有一种将责任转交给调用者的好方法,这样实现的库就不需要对提供的映射函数中是否需要上下文做出任何假设?
或者仅仅是一个事实,异步方法组成得不是很好,没有各种假设?
只是为了澄清一些事情:
ConfigureAwait(false)将导致空同步.上下文.正如一些答案所提到的那样,可以在方法中添加一个bool-flag,但正如我所看到的,这也不是太漂亮,因为它必须一直传播到API中(因为它有)更多"实用"功能,取决于上面显示的功能.
c# task synchronizationcontext task-parallel-library async-await
执行以下操作之间有什么区别:
async Task<T> method(){
var r = await dynamodb.GetItemAsync(...)
return r.Item;
}
Run Code Online (Sandbox Code Playgroud)
VS
async Task<T> method(){
var task = dynamodb.GetItemAsync(...)
return task.Result.Item;
}
Run Code Online (Sandbox Code Playgroud)
在我的情况下,由于某种原因,只有第二个工作.第一个似乎永远不会结束.
我有一些文件要上传,一些文件失败,因为帖子是异步的而不是同步的..
我正在尝试将此调用作为同步调用..
我想等待回应.
如何将此调用设为同步?
static async Task<JObect> Upload(string key, string url, string
sourceFile, string targetFormat)
{
using (HttpClientHandler handler = new HttpClientHandler {
Credentials = new NetworkCredential(key, "")
})
using (HttpClient client = new HttpClient(handler))
{
var request = new MultipartFormDataContent();
request.Add(new StringContent(targetFormat), "target_format");
request.Add(new StreamContent(File.OpenRead(sourceFile)),
"source_file",
new FileInfo(sourceFile).Name);
using (HttpResponseMessage response = await client.PostAsync(url,
request).ConfigureAwait(false))
using (HttpContent content = response.Content)
{
string data = await content.ReadAsStringAsync().ConfigureAwait(false);
return JsonObject.Parse(data);
}
}
}
Run Code Online (Sandbox Code Playgroud)
任何帮助赞赏!
我的应用程序需要将插件加载到单独的应用程序域中,然后异步执行其中的一些代码.我编写了一些代码来包装可Task编组类型:
static class RemoteTask
{
public static async Task<T> ClientComplete<T>(RemoteTask<T> remoteTask,
CancellationToken cancellationToken)
{
T result;
using (cancellationToken.Register(remoteTask.Cancel))
{
RemoteTaskCompletionSource<T> tcs = new RemoteTaskCompletionSource<T>();
remoteTask.Complete(tcs);
result = await tcs.Task;
}
await Task.Yield(); // HACK!!
return result;
}
public static RemoteTask<T> ServerStart<T>(Func<CancellationToken, Task<T>> func)
{
return new RemoteTask<T>(func);
}
}
class RemoteTask<T> : MarshalByRefObject
{
readonly CancellationTokenSource cts = new CancellationTokenSource();
readonly Task<T> task;
internal RemoteTask(Func<CancellationToken, Task<T>> starter)
{
this.task = starter(cts.Token);
}
internal void Complete(RemoteTaskCompletionSource<T> tcs)
{
task.ContinueWith(t …Run Code Online (Sandbox Code Playgroud) 如何避免为异步和非异步方法编写相同的代码两次.我目前正在使用ASP.NET,因此我目前正在使用请求线程,并且我很快就知道他在代码下面(应该显示我的意图),这肯定是错误的做法.
应用程序死锁,因为await关键字试图返回.Result阻塞的同一线程.
我这样做的全部原因是避免两次编写相同的"FindAll"代码.
public IEnumerable<Resource> FindAll()
{
return FindAllAsync().Result;
}
public async Task<IEnumerable<Resource>> FindAllAsync()
{
return await Context.Resources.ToListAsync();
}
Run Code Online (Sandbox Code Playgroud)
那你怎么解决这个问题呢?
我正在尝试了解服务结构的一些最佳实践.
如果我有一个由Web服务或其他机制添加的队列和后端任务来处理该队列,那么在后台处理长时间运行的操作的最佳方法是什么.
两种方式都有点不对劲,但如果有更好的方法我就无法解决.
c# ×9
async-await ×5
.net ×3
asp.net-mvc ×2
asynchronous ×2
deadlock ×2
task ×2
appdomain ×1
dispose ×1
httpresponse ×1