使用Async / Await的Comet样式的API消耗

时间:2018-09-21 23:18:01

标签: c# async-await comet

我正在尝试从您连接到的Comet样式HTTP API中读取内容,并且该API会不断推送事件。我希望它在启动后在后台运行,但是我的Async / Await是错误的,它冻结了我的UI,我不知道为什么。

private async void button1_Click(object sender, EventArgs e)
{
    await Task.Run((Func<Task>)PushEventReader);
}

public async Task PushEventReader()
{
    var uri = "url.to/api";
    var client = new WebClient();

    client.OpenReadCompleted += async (sender, e) =>
    {
        using (var reader = new StreamReader(e.Result))
        {
            while (!reader.EndOfStream)
            {
                var line = await reader.ReadLineAsync();
                Console.WriteLine(line);
            }
        }
    };
    await client.OpenReadTaskAsync(new Uri(uri));
}

1 个答案:

答案 0 :(得分:1)

如果您的按钮单击事件只不过是在后台启动作业,那么与async异步就没有任何意义,而等待Task.Run也没有意义,因为您什么都不做之后。您可以像这样简单地单击按钮:

private void button1_Click(object sender, EventArgs e)
{
    Task.Run(async () => await PushEventReader());
}

Task.Run会将您传递给它的所有工作排队,以便在ThreadPool上运行,这将有效地使其在后台运行。

其他:您使用的WebClient是非托管资源(您会注意到,由于它实现了IDisposable接口),因此,这是一个好习惯在using块中使用它们,它将为您处理处置:

public async Task PushEventReader()
{
    var uri = "url.to/api";

    using (var client = new WebClient())
    {
        client.OpenReadCompleted += async (sender, e) =>
        {
            using (var reader = new StreamReader(e.Result))
            {
                while (!reader.EndOfStream)
                {
                    var line = await reader.ReadLineAsync();
                    Console.WriteLine(line);
                }
            }
        };

        await client.OpenReadTaskAsync(new Uri(uri));
    }
}