处理多个嵌套的异步

时间:2015-11-03 14:05:36

标签: c# multithreading async-await

我遇到了使用异步方法的问题 - 即嵌套异步。

我开始后台任务:

public sealed class StartupTask : IBackgroundTask
{
    public async void Run(IBackgroundTaskInstance taskInstance)
    {
        taskInstance.GetDeferral();
        ServerWorkers.WebServer server = new ServerWorkers.WebServer();
        await ThreadPool.RunAsync(workItem =>
         {
             AnotherSync.Get();
             server.Start();
         });
    }

    public static async void Get()
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(Shared.URL);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Shared.HeaderType));
            using (var response = await client.GetAsync(route + "?" + GeneralTags.COMPANY_REF + "=" + ApplicationObject.CompanyRef)) //.Result)
            {
                if (response.IsSuccessStatusCode)
                {
                    ApplicationObject.PrintData = JsonConvert.DeserializeObject<Model.Print>(response.Content.ReadAsStringAsync().Result);
                }
                else
                {
                    evError(new Exception(String.Format("{0}: {1}", (int)response.StatusCode, response.ReasonPhrase)), ErrorTags.PRINT_GET);
                }
            }
        }
    }

internal class WebServer
{
    private const uint BufferSize = 8192;

    public void Start()
    {
        StreamSocketListener listener = new StreamSocketListener();

        listener.BindServiceNameAsync("8080");

        listener.ConnectionReceived += async (sender, args) =>
        {
            StringBuilder request = new StringBuilder();
            using (IInputStream input = args.Socket.InputStream)
            {
                byte[] data = new byte[BufferSize];
                IBuffer buffer = data.AsBuffer();
                uint dataRead = BufferSize;
                while (dataRead == BufferSize)
                {
                    await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
                    request.Append(Encoding.UTF8.GetString(data, 0, data.Length));
                    dataRead = buffer.Length;
                }
            }

            using (IOutputStream output = args.Socket.OutputStream)
            {
                using (Stream response = output.AsStreamForWrite())
                {
                    byte[] bodyArray = Encoding.UTF8.GetBytes("<html><body>Hello, World!</body></html>");
                    var bodyStream = new MemoryStream(bodyArray);

                    var header = "HTTP/1.1 200 OK\r\n" +
                                $"Content-Length: {bodyStream.Length}\r\n" +
                                    "Connection: close\r\n\r\n";

                    byte[] headerArray = Encoding.UTF8.GetBytes(header);
                    await response.WriteAsync(headerArray, 0, headerArray.Length);
                    await bodyStream.CopyToAsync(response);
                    await response.FlushAsync();
                }
            }
        };
    }
}

然后我的应用程序充当Web服务器..它不会退出。

如果我添加这个,那么我有:

  public async void Run(IBackgroundTaskInstance taskInstance)
    {
        taskInstance.GetDeferral();
        ServerWorkers.WebServer server = new ServerWorkers.WebServer();
        await ThreadPool.RunAsync(workItem =>
         {
             AnotherSync.Get();
             AnotherSync.Get();
             server.Start();
         });
    }

internal  class AnotherSync
{
    public static event delError evError;
    private const string route = "/api/Print";

    static wsPrint.IPrint wsPrint = new wsPrint.PrintClient();

    public static void Get()
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(Shared.URL);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Shared.HeaderType));
            using (var response =  client.GetAsync(route + "?" + GeneralTags.COMPANY_REF + "=" + ApplicationObject.CompanyRef).Result)
            {
                if (response.IsSuccessStatusCode)
                {
                    ApplicationObject.PrintData = JsonConvert.DeserializeObject<Model.Print>(response.Content.ReadAsStringAsync().Result);
                }
                else
                {
                    evError(new Exception(String.Format("{0}: {1}", (int)response.StatusCode, response.ReasonPhrase)), ErrorTags.PRINT_GET);
                }
            }
        }
    }       
}

然后应用程序存在。

我可能会弄错,但是因为我使用的是嵌套的异步方法吗?

1 个答案:

答案 0 :(得分:1)

这是一个线程应该是什么样子的例子,

public sealed class StartupTask : IBackgroundTask
{
    //has to be declared here to keep the handle alive and prevent garbage collection
    private ServerWorkers.WebServer server = new ServerWorkers.WebServer();



    public async void Run(IBackgroundTaskInstance taskInstance)
    {
        //Start the server running no need for await as its an synchronous
        server.Start();

        //don't exit until work is compelted
        while(server.Running)
        {
            //give up processor and allow other work to occur while you are waiting
            await Task.Yield();
        }
    }

    internal class WebServer
    {
        private const uint BufferSize = 8192;
        private StreamSocketListener listener;
        public bool Running { get; private set;}= false;

        public void Start()
        {
            Lock(this){//prevent any other code interupting
                if(!Running )//prevent multiple starts
                {
                    listener = new StreamSocketListener();
                    listener.BindServiceNameAsync("8080");
                    listener.ConnectionReceived += listener_ConnectionReceived;
                    Running = true;
                }
            }
        }
        public void Stop()
        {
            Lock(this){//prevent any other code interupting
                listener.Close();
                listener.Dispose();
                listener = null;
                Running = false;
            }
        }
        public void listener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
        { 
            //process data from listerner's event
        }
    }
}

注意我没有使用Windows应用程序框架,因此可能会有所不同