【问题标题】:Visual Studio - program ends before asynchronous tasks can finish - C#Visual Studio - 程序在异步任务完成之前结束 - C#
【发布时间】:2018-02-26 07:32:46
【问题描述】:

这可能有一个简单的答案,我只是找不到它,而且我是 C# 新手。

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

我的问题来了,当 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
    }
}

谢谢。

【问题讨论】:

    标签: c# visual-studio asynchronous


    【解决方案1】:

    从 C# 6.0 开始,您可以在 catch 块中使用 await,从 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

    【讨论】:

    • 谢谢,这确实有效。我必须先将<LangVersion>latest</LangVersion> 添加到我的.csproj 文件中。我还必须将 Main 的返回类型更改为 Task 而不是 void(并添加 static 关键字)
    • 你可以在 VS 2017 中设置。在 Build->Advanced
    【解决方案2】:

    这是因为您没有等到任务完成。使用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 可以积累很多已经完成的任务。仅作为思考的例子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-16
      • 2017-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-03
      • 2017-03-17
      相关资源
      最近更新 更多