1

我正在用 C# 编写一个 .Net 控制台应用程序。

我需要将基于事件的线程调用转换为异步方法。

例如 :

public class WorkerClass
    {
        public EventHandler Progress;
        public EventHandler Finished;
        public void DoSomething()
        {
            Thread td = new Thread(Start);
            td.Name = "Worker Thread";
            td.Start();
        }

        private void Start()
        {
            int i = 0;
            while (i < 10)
            {
                Thread.Sleep(1000);
                i++;
                var progress = i * 10;
                Progress?.Invoke((object)progress, null);
            }
            Finished?.Invoke(null, null);
        }
    }



    Class MyMainClass
            {
                private static WorkerClass myWorkerClass;
                static void Main(string[] args)
                {
                    myWorkerClass = new WorkerClass();
                    RunAsynchronously(null);
                }
                private async void RunAsynchronously(EventHandler progress)        
                {           
                    //Main Thread Call

                    await DoSomethingAsync(progress);

                    //Resume after worker finished is not in main thread? :(
                    //Needed main thread to continue
                }
                private Task<int> DoSomethingAsync(EventHandler progress)
                {
                    var completionSource = new TaskCompletionSource<int>();

                    EventHandler Progress = null;
                    EventHandler Finished = null;

                    Finished = (o, e) =>
                    {
                        myWorkerClass.Finished -= Finished;
                        myWorkerClass.Progress -= Progress;
                        completionSource.SetResult(100);
                    };

                    Progress = (o, e) => { progress?.Invoke(o, e); };

                    myWorkerClass.Finished += Finished;
                    myWorkerClass.Progress += Progress;

                    myWorkerClass.DoSomething();            

                    return completionSource.Task;
                }
            }

由于某些限制,我需要主线程继续,但是在等待恢复 RunAsynchronously 方法后,当前线程与主线程(或调用等待的线程)不同。

我知道如果调用者是 UI 线程,这种行为会自动起作用,但在我的情况下,它是控制台应用程序并且我没有 UI。

请提出解决方案。提前致谢。

4

1 回答 1

1

我觉得您对控制台应用程序的期望和 .NET 应用程序的线程模型有一个基本的误解。

控制台应用程序一直运行到其入口线程完成该Main方法的执行。这意味着您要么让线程忙于工作,要么阻塞线程,直到另一个信号解除阻塞并允许方法退出。这是一个非常简单的结构,旨在让您启动应用程序,做一些工作,然后在完成后退出。这意味着线程永远不会“自由”地做其他工作;如果不将工作调度模型完全更改为更复杂的模型,则无法安排任务在此线程上继续。

在基于 UI 的应用程序中,您的应用程序遵循更复杂的模型。不是应用程序做一些工作,然后退出,而是要求主线程泵送一个消息队列,根据收到的消息做工作,只有在收到“退出”消息时才退出。该模型采用单个线程并为其提供一个工作队列,每件工作都由一条消息发出信号。这就是允许您Task在 UI 线程上进行简历的原因。


这种混淆就是为什么该async void模式通常被认为是一种反模式,当然也就是为什么它只能在带有 UI 的应用程序中使用。由于非常具体的任务调度模型,该应用程序才能正常工作。任何其他模型都会导致此构造中断,吞下异常并且无法知道工作何时完成。

于 2018-06-04T12:55:27.780 回答