Visual Studio - 程序在异步任务完成之前结束 - C#

时间:2018-02-26 07:32:47

标签: c# visual-studio asynchronous

对此可能有一个简单的答案,我无法找到它,而且我是C#的新手。

使用Visual Studio,我编写了一个函数,将文本写入文件异步(使用async / await,并且不返回任何内容),但是在接近结束时调用它我的程序(我正在测试它),所以现在当它到达await时,程序继续从我调用函数的地方(接近我的Main的末尾),而文本是忙于异步写入文件。

我的问题进来了,当Main结束时,程序完成并退出所有其他异步任务,甚至在任何事情都可以写入文件之前(因为在它实际写入之前必须经历一个完整的过程)文件)。我可以让我的主sleep持续一两秒,但我更愿意知道如何在继续之前等待所有后台异步任务完成(不使用Main中的另一个await / async)

我知道你可能在想为什么我不能让它同步,因为它在程序的最后(我正在测试它),但我需要这样,并希望知道如何做到这一点。

void Main(string[] args)
{
    try
    {
        throw new Exception("This is an error\n");
    }
    catch (Exception ex)
    {
        LogError.ToFile(ex);
    }
    //need code here to wait for background processes to finish before ending
}

public class LogError
{
    static public void ToFile(Exception excep)
    {
        Task.Run(() => LogErrorToFile(excep));
    }

    static public async Task LogErrorToFile(Exception excep)
    {
        //writes to file using await
    }
}

感谢。

2 个答案:

答案 0 :(得分:1)

从C#6.0开始,您可以在await块中使用catch,在C#7.0 / 7.1中,您可以使用async Main,因此您可以将代码重写为此

async void Main(string[] args)
{
    try
    {
        throw new Exception("This is an error\n");
    }
    catch (Exception ex)
    {
        await LogError.LogErrorToFile(ex);
    }
}

如果你不能使用它,你需要暴露使用的Task并等待它完成或使用某种同步机制,如ManualResetEvent

答案 1 :(得分:0)

这是因为您不必等到任务完成。使用Task.Wait等待任务完成。或者Task.WaitAll等待完成多个任务。为此,您必须收集缓冲区中的所有任务,例如List<Task>

void Main(string[] args)
{
    try
    {
        throw new Exception("This is an error\n");
    }
    catch (Exception ex)
    {
        LogError.ToFile(ex);
    }
    LogError.WaitForCompletion();
    //need code here to wait for background processes to finish before ending
}

public class LogError
{
    private static Task _tasks = new List<Task>();

    static public void ToFile(Exception excep)
    {
        _tasks.add(Task.Run(() => LogErrorToFile(excep)));
    }

    static public async Task LogErrorToFile(Exception excep)
    {
        //writes to file using await
    }

    public static void WaitForCompletion() {
        Task.WaitAll(_tasks);
    }
}

此代码不适用于生产,因为在其中_tasks字段可以累积许多已完成的任务。仅用它作为思考的一个例子。