我正在尝试基于VS2013项目模板中的示例AccountController为ASP.NET MVC5网站设置电子邮件确认.我已经实现了IIdentityMessageService使用SmtpClient,试图尽可能简单:
public class EmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
using(var client = new SmtpClient())
{
var mailMessage = new MailMessage("some.guy@company.com", message.Destination, message.Subject, message.Body);
await client.SendMailAsync(mailMessage);
}
}
}
Run Code Online (Sandbox Code Playgroud)
调用它的控制器代码直接来自模板(由于我想排除其他可能的原因,因此将其解压缩为单独的操作):
public async Task<ActionResult> TestAsyncEmail()
{
Guid userId = User.Identity.GetUserId();
string code = await UserManager.GenerateEmailConfirmationTokenAsync(userId);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = userId, code = code }, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(userId, "Confirm your account", "Please confirm your account by clicking <a …Run Code Online (Sandbox Code Playgroud) 它建议使用一个ConfigureAwait(false)当你可以随时,特别是在图书馆,因为它可以帮助避免死锁和提高性能.
我编写了一个大量使用异步的库(访问数据库的Web服务).图书馆的用户遇到了僵局,经过多次痛苦的调试和修补后,我将其追踪到了单独使用await Task.Yield().我使用过的其他任何地方.ConfigureAwait(false),但是不支持Task.Yield().
对于需要等效的情况,推荐的解决方案是Task.Yield().ConfigureAwait(false)什么?
我已经读过有关如何SwitchTo移除某个方法的内容.我可以看出为什么那可能是危险的,但为什么没有相应的Task.Yield().ConfigureAwait(false)?
编辑:
为了提供我的问题的进一步背景,这里有一些代码.我正在实现一个开源库,用于访问支持异步的DynamoDB(作为AWS的服务的分布式数据库).IX-Async库IAsyncEnumerable<T>提供了许多操作返回.该库不提供从以"块"提供行的数据源生成异步枚举的好方法,即每个异步请求返回许多项.所以我有自己的通用类型.该库支持预读选项,允许用户指定在调用实际需要之前应该请求多少数据.MoveNext()
基本上,这是如何工作的,我通过调用GetMore()和传递这些块之间的状态来请求块.我将这些任务放入chunks队列并将它们出列并将它们转换为我放在单独队列中的实际结果.这个NextChunk()方法就是问题所在.根据值的不同,ReadAhead我会在完成最后一个(最多)之后保持获取下一个块,直到需要一个值但不可用(无)或仅获取超出当前使用值的下一个块(一些).因此,获取下一个块应该并行/不阻止获取下一个值.枚举器代码是:
private class ChunkedAsyncEnumerator<TState, TResult> : IAsyncEnumerator<TResult>
{
private readonly ChunkedAsyncEnumerable<TState, TResult> enumerable;
private readonly ConcurrentQueue<Task<TState>> chunks = new ConcurrentQueue<Task<TState>>();
private readonly Queue<TResult> results = new Queue<TResult>();
private CancellationTokenSource cts = new CancellationTokenSource();
private TState lastState;
private TResult current;
private …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用C#5 async/await功能创建SignalR应用程序,但无论何时运行代码,它都会抛出System.InvalidOperationException.这是重现问题的最简单的代码.
public class SampleHub : Hub
{
public Task<string> GetGoogle()
{
var http = new WebClient();
return http.DownloadStringTaskAsync("http://www.google.com");
}
}
Run Code Online (Sandbox Code Playgroud)
例外细节:
此时无法启动异步操作.异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动.如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async = \"true \"%>.
堆栈跟踪:
at System.Web.AspNetSynchronizationContext.OperationStarted()
at System.Net.WebClient.DownloadStringAsync(Uri address, Object userToken)
at System.Net.WebClient.DownloadStringTaskAsync(Uri address)
at System.Net.WebClient.DownloadStringTaskAsync(String address)
Run Code Online (Sandbox Code Playgroud)
在客户端,Javascript看起来像这样.
$.connection.hub.start().done(function () {
$('#google').click(function () {
var google = sample.server.getGoogle();
console.log(google);
});
});
Run Code Online (Sandbox Code Playgroud)
我做错了什么?有没有解决方法?我真的很想坚持使用C#中的异步/等待模式,如果可能的话.
我正在使用SignalR 1.1.2,我遇到了异步集线器方法的问题.使用ForeverFrame传输在我的PC上一切正常,但在服务器上部署并切换到Web套接字传输后,我收到以下错误:
此时无法启动异步操作.异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动.如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async ="true"%>.
我的中心方法代码:
public async Task<string> getUrl()
{
var url = await MyWebservice.GetMyRoomUrlAsync(Context.User.Identity.Name);
return url;
}
Run Code Online (Sandbox Code Playgroud)
SignalR中是否支持使用Web套接字传输的异步方法?
更新:GetMyRoomUrlAsync代码:
public static Task<string> GetMyRoomUrlAsync(string email)
{
var tcs = new TaskCompletionSource<string>();
var client = new Onif40.VisualStudioGeneratedSoapClient();
client.GetRoomUrlCompleted += (s, e) =>
{
if (e.Error != null)
tcs.TrySetException(e.Error);
else if (e.Cancelled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(e.Result);
};
client.GetRoomUrlAsync(email);
return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)
在Stephen Cleary澄清问题所在之后,通过将EAP重写为APM来解决问题是微不足道的.
public static Task<string> GetMyRoomUrlAsync(string email)
{
var tcs = new TaskCompletionSource<string>();
var client = new Onif40.VisualStudioGeneratedSoapClient();
client.BeginGetRoomUrl(email, iar …Run Code Online (Sandbox Code Playgroud) async-await ×3
c# ×3
signalr ×2
.net ×1
.net-4.5 ×1
asp.net ×1
asp.net-mvc ×1
signalr-hub ×1
smtpclient ×1