什么时候使用 Task.Run 是浪费或妄想?
When is using Task.Run wasteful or delusional?
我有一个接口,reads/writes 存储一个对象。在一种情况下,存储是具有异步方法的数据库。在另一种情况下,它只是一个 cookie。
我收集到它建议沿着以异步调用结束的路径使用异步返回,因此接口也是异步的似乎也有意义。但在 cookie 的情况下,我只是设置了几个字段并将其粘贴在响应中,因此那里还没有任何异步。我可以将该位包装在 await Task.Run() 中以匹配新界面,但我不知道这是否可取,或者它是否会对性能产生一些负面影响。
怎么办?
public interface IProfileStore
{
async Task SetProfile(UserProfile profile);
}
public async Task SetProfile(UserProfile profile)
{
// Look mom, I'm needlessly async
await Task.Run(() =>
{
var cookie = new HttpCookie(AnonymousCookieName);
cookie["name"] = profile.FullName;
HttpContext.Current.Response.Cookies.Add(cookie);
});
}
如果您正在执行一个非常短的快速完成的操作,那么您可能不需要使用 Task.Run
将工作推送到另一个线程,这是非常正确的。在线程池中调度代码的行为可能比 只是这样做 .
花费更长的时间
至于如何做到这一点,只需删除您不需要的 await Task.Run
,瞧,一切就绪。您有一个同步操作仍然包装在 Task
中,因此仍然匹配所需的接口。
你不应该那样做;你只是在创建不必要的线程池流失。
相反,从方法中删除 async
关键字并简单地 return Task.FromResult(0)
到 return 一个同步完成的任务
几乎如 SLaks 所建议的那样,如果你正在做一些异步的事情,但 return 任务,那么:
public Task SetProfile(UserProfile profile)
{
return Task.Run(() =>
{
var cookie = new HttpCookie(AnonymousCookieName);
cookie["name"] = profile.FullName;
HttpContext.Current.Response.Cookies.Add(cookie);
});
}
然而,正如他在这种情况下所建议的那样:
public Task SetProfile(UserProfile profile)
{
var cookie = new HttpCookie(AnonymousCookieName);
cookie["name"] = profile.FullName;
HttpContext.Current.Response.Cookies.Add(cookie);
return Task.FromResult(null);
}
Return null 作为系统缓存的已完成任务。
我有一个接口,reads/writes 存储一个对象。在一种情况下,存储是具有异步方法的数据库。在另一种情况下,它只是一个 cookie。
我收集到它建议沿着以异步调用结束的路径使用异步返回,因此接口也是异步的似乎也有意义。但在 cookie 的情况下,我只是设置了几个字段并将其粘贴在响应中,因此那里还没有任何异步。我可以将该位包装在 await Task.Run() 中以匹配新界面,但我不知道这是否可取,或者它是否会对性能产生一些负面影响。
怎么办?
public interface IProfileStore
{
async Task SetProfile(UserProfile profile);
}
public async Task SetProfile(UserProfile profile)
{
// Look mom, I'm needlessly async
await Task.Run(() =>
{
var cookie = new HttpCookie(AnonymousCookieName);
cookie["name"] = profile.FullName;
HttpContext.Current.Response.Cookies.Add(cookie);
});
}
如果您正在执行一个非常短的快速完成的操作,那么您可能不需要使用 Task.Run
将工作推送到另一个线程,这是非常正确的。在线程池中调度代码的行为可能比 只是这样做 .
至于如何做到这一点,只需删除您不需要的 await Task.Run
,瞧,一切就绪。您有一个同步操作仍然包装在 Task
中,因此仍然匹配所需的接口。
你不应该那样做;你只是在创建不必要的线程池流失。
相反,从方法中删除 async
关键字并简单地 return Task.FromResult(0)
到 return 一个同步完成的任务
几乎如 SLaks 所建议的那样,如果你正在做一些异步的事情,但 return 任务,那么:
public Task SetProfile(UserProfile profile)
{
return Task.Run(() =>
{
var cookie = new HttpCookie(AnonymousCookieName);
cookie["name"] = profile.FullName;
HttpContext.Current.Response.Cookies.Add(cookie);
});
}
然而,正如他在这种情况下所建议的那样:
public Task SetProfile(UserProfile profile)
{
var cookie = new HttpCookie(AnonymousCookieName);
cookie["name"] = profile.FullName;
HttpContext.Current.Response.Cookies.Add(cookie);
return Task.FromResult(null);
}
Return null 作为系统缓存的已完成任务。