尝试在c#控制台应用程序中运行多个异步任务

时间:2014-09-27 17:24:21

标签: c# asynchronous visual-studio-2013 console-application

我有一个main方法从另一个类调用方法,这些方法都是异步的Task方法但不返回任何内容。他们正在向REST API客户端发送get请求。 这是一个名为DbRequestHandler的类中一个方法的示例:

public static async Task ReadRooms(HttpClient client)
{
    // HTTP GET all rooms
    HttpResponseMessage response = await client.GetAsync("api/v1/rooms");

    if (response.IsSuccessStatusCode)
    {
        StreamWriter file = new StreamWriter("xmlRooms.xml", false);

        string rooms = await response.Content.ReadAsStringAsync();
        file.Write(rooms);
        file.Flush();

        Console.Out.Write(rooms);
        Console.ReadKey();
    }
}

以下是通过调用DbRequestHandler来运行程序的Main方法:

static void Main(string[] args)
{
    var url = System.Configuration.ConfigurationManager.AppSettings["CentrisURL"];

    if (url == null)
    {
        Console.WriteLine("Failed to load API url");
    }

    var client = new HttpClient();
    client.BaseAddress = new Uri(url);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

    //DbRequestHandler.ReadRooms(client).Wait();
    //DbRequestHandler.ReadRoomsType(client).Wait();
    //DbRequestHandler.ReadCourses(client).Wait();
    DbRequestHandler.ReadTeachers(client).Wait();
}

我的问题是我似乎无法弄清楚如何调用所有这些单独的方法都是异步的任务方法,我知道它与.Wait()有关但我还没有找到正确的解决方案,我尝试过几个。如果我取消对DbRequestHandler方法的所有调用的注释,则第一行是唯一执行的行。是否有人建议如何解决这个问题?我很难理解异步任务。希望我的问题很明确。我会阅读你推荐阅读的任何链接,但我不能保证我会理解:P

4 个答案:

答案 0 :(得分:3)

  

如果我取消对DbRequestHandler方法的所有调用的注释,则第一行是唯一执行的行。

这听起来像你的实际应用程序一个控制台应用程序,就像你发布的那个。我认为没有理由说你的原始代码不起作用。我只是运行你的代码,它执行了两种方法就好了。

如果你想连续地(一个接一个地)进行异步工作,那么你应该使用await

await DbRequestHandler.ReadRoomsAsync(client);
await DbRequestHandler.ReadRoomsTypeAsync(client);
...

如果您想同时执行所有异步工作,则应使用await Task.WhenAll

await Task.WhenAll(DbRequestHandler.ReadRoomsAsync(client),
    DbRequestHandler.ReadRoomsTypeAsync(client), ...);

无论哪种方式,如果您将其放入控制台应用中,我建议您将Main更改为仅调用另一种方法并Wait,如下所示:

static void Main(string[] args)
{
  MainAsync().Wait();
}

static async Task MainAsync()
{
  var url = System.Configuration.ConfigurationManager.AppSettings["CentrisURL"];
  ...
}

这可以将阻止代码保留在Main所属的地方,而不是其他任何地方,从而帮助您的代码保持清洁。

答案 1 :(得分:1)

static async void Main(string[] args)
{
    var url = System.Configuration.ConfigurationManager.AppSettings["CentrisURL"];

    if (url == null)
    {
        Console.WriteLine("Failed to load API url");
    }

    var client = new HttpClient();
    client.BaseAddress = new Uri(url);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

    await Task.WhenAll(
        new Task[] {
            DbRequestHandler.ReadRooms(client),
            DbRequestHandler.ReadRoomsType(client),
            DbRequestHandler.ReadCourses(client),
            DbRequestHandler.ReadTeachers(client),
        }
    );
}

答案 2 :(得分:1)

在处理async-await和控制台应用程序时,您总是会在自定义SynchronizationContext(例如Winforms或WPF)的地方做您不会做的事情。

在您的示例中,您可以对main中执行的所有任务使用Task.WaitAll,只需等待它们全部完成:

Task readRoomsTask = DbRequestHandler.ReadRooms(client);

Task readRoomTypeTask = DbRequestHandler.ReadRoomsType(client);
Task readCoursesTask = DbRequestHandler.ReadCourses(client);
Task readTeachersTask = DbRequestHandler.ReadTeachers(client);

Task.WaitAll(readRoomsTask, readRoomTypeTask, reachCoursesTask, reqdTeachersTask);

答案 3 :(得分:-1)

解决此问题的最佳方法是创建一系列任务,然后等待所有任务完成

if (url == null)
        {
            Console.WriteLine("Failed to load API url");
        }

        var client = new HttpClient();
        client.BaseAddress = new Uri(url);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
       Task[] taskArray = new Task[4];
       taskArray[0] = Task.Factory.StartNew(await DbRequestHandler.ReadRooms(client));
       taskArray[1] = Task.Factory.StartNew(DbRequestHandler.ReadRoomsType(client));
       taskArray[2] = Task.Factory.StartNew(DbRequestHandler.ReadCourses(client));
       taskArray[3] = Task.Factory.StartNew(DbRequestHandler.ReadTeachers(client));
       Task.WaitAll(taskArray);

有关运行多项任务的更多信息,请访问msdn enter link description here