C#异步等待HTTP服务器偶尔失败

时间:2017-08-12 18:42:39

标签: c# entity-framework http async-await

我在一个简单的HTTP服务器上发生了统计崩溃,我写道, 尝试使用异步和等待使其异步单线程。

有时我会收到错误:

  

未处理的异常:System.AggregateException:发生了一个或多个错误。 ---> System.NotSupportedException:在上一个异步操作完成之前,在此上下文中启动了第二个操作。使用'等待'确保在调用此上下文中的另一个方法之前已完成任何异步操作。不保证任何实例成员都是线程安全的。

我似乎并不明白这是什么意思。是不是await的全部目的是能够在第一个操作时调用第二个操作?

相关代码是:

private static readonly BugScapeDbContext DBContext = new BugScapeDbContext();
private readonly CancellationToken _cancel = new CancellationToken();

public BugScapeServer() { }
public async Task Run() {
    var listener = new HttpListener();

    listener.Prefixes.Add("http://localhost:8081/");
    listener.Prefixes.Add("http://127.0.0.1:8081/");

    listener.Start();

    var saveChangesTask = PeriodicTask(SaveDBChangesAsync, TimeSpan.FromMilliseconds(10), this._cancel);

    while (!this._cancel.IsCancellationRequested) {
        await HandleRequestAsync(listener.GetContext());
    }

    await saveChangesTask;
}

private static async Task PeriodicTask(Func<Task> task, TimeSpan interval, CancellationToken token) {
    while (!token.IsCancellationRequested) {
        try {
            await task();
        } catch (Exception e) {
            Console.WriteLine("Exception {0}", e.ToString());
        }
        await Task.Delay(interval, token);
    }
}

private static async Task SaveDBChangesAsync() {
    if (!DBContext.ChangeTracker.HasChanges()) return;
    Console.WriteLine("Saving Changes...");
    await DBContext.SaveChangesAsync();
}
private static async Task HandleRequestAsync(object state) {
    var context = (HttpListenerContext)state;
    var streamReader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding);
    dynamic reqJson = await JsonConvert.DeserializeObjectAsync(await streamReader.ReadToEndAsync());
    BugScapeResponse response;

    switch ((EBugScapeOperation)reqJson.Operation) {
    case EBugScapeOperation.GetMapState:
        Console.WriteLine("Getting map state");
        response = await HandleMapStateRequestAsync(reqJson);
        break;
    case EBugScapeOperation.Move:
        Console.WriteLine("Moving character");
        response = await HandleMoveRequestAsync(reqJson);
        break;
    default:
        Console.WriteLine("Invalid operation {0}", (EBugScapeOperation)reqJson.Operatrion);
        return;
    }

    if (response == null) {
        response = new BugScapeResponse(EBugScapeResult.Error);
    }

    context.Response.ContentEncoding = Encoding.UTF8;
    var resStream = new StreamWriter(context.Response.OutputStream, context.Response.ContentEncoding);
    await resStream.WriteAsync(await JsonConvert.SerializeObjectAsync(response));
    await resStream.FlushAsync();
    context.Response.Close();
}
private static async Task<BugScapeResponse> HandleMapStateRequestAsync(dynamic request) {
    var character = await DBContext.Characters.FindAsync(new object[] { (int)request.CharacterID });
    if (character != null) return new BugScapeMapResponse(character.Map);

    Console.WriteLine("No characeter found");
    return null;
}
private static async Task<BugScapeResponse> HandleMoveRequestAsync(dynamic request) {
    var character = await DBContext.Characters.FindAsync(new object[] { (int)request.CharacterID });
    if (character == null) {
        Console.WriteLine("No characeter found");
        return null;
    }

    character.Move((EDirection)request.Direction);
    return new BugScapeResponse(EBugScapeResult.Success);
}

完整堆栈跟踪是:

  

未处理的异常:System.AggregateException:发生了一个或多个错误。 ---&GT; System.NotSupportedException:在上一个异步操作完成之前,在此上下文中启动了第二个操作。使用&#39;等待&#39;确保在调用此上下文中的另一个方法之前已完成任何异步操作。任何实例成员都不保证是线程安全的。          在System.Data.Entity.Internal.ThrowingMonitor.EnsureNotEntered()          在System.Data.Entity.Internal.Linq.InternalSet 1.FindAsync(CancellationToken cancellationToken, Object[] keyValues) at System.Data.Entity.DbSet 1.FindAsync(CancellationToken cancellationToken,Object [] keyValues)          在System.Data.Entity.DbSet`1.FindAsync(Object [] keyValues)          在C:\ Users \ Bugale \ documents \ visual studio 2015 \ Projects \ BugScape \ BugScape \ Server.cs中的BugScape.BugScapeServer.d__8.MoveNext():第108行       ---从抛出异常的先前位置开始的堆栈跟踪结束---          在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)          在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)          在CallSite.Target(Closure,CallSite,Object)          在C:\ Users \ Bugale \ documents \ visual studio 2015 \ Projects \ BugScape \ BugScape \ Server.cs中的BugScape.BugScapeServer.d__6.MoveNext():第83行       ---从抛出异常的先前位置开始的堆栈跟踪结束---          在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)          在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)          在System.Runtime.CompilerServices.TaskAwaiter.GetResult()          在C:\ Users \ Bugale \ documents \ visual studio 2015 \ Projects \ BugScape \ BugScape \ Server.cs中的BugScape.BugScapeServer.d__3.MoveNext():第48行          ---内部异常堆栈跟踪结束---          在System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)          在System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout,CancellationToken cancellationToken)          在System.Threading.Tasks.Task.Wait()          位于C:\ Users \ Bugale \ documents \ visual studio 2015 \ Projects \ BugScape \ BugScape \ Program.cs:第12行的BugScape.Program.Main(String [] args)

0 个答案:

没有答案