【问题标题】:C# Winform Multithread sequenceC# Winform 多线程序列
【发布时间】:2011-04-05 23:06:42
【问题描述】:

我对 C# 和一般编码相对较新。我正在尝试编写一个具有一些逻辑并且还通过进度条指示进度的程序。我正在 Main() 中启动一个线程,它执行我所有的业务逻辑。它具有在我需要更新进度条的点触发的事件。

Form 对象订阅业务逻辑事件并具有线程安全的委托,这些委托被调用以更新进度条和文本标签。

我的问题是,由于Form是在主线程中启动的,所以我必须在Application.Run()之前启动业务逻辑线程。当第一个 ProgressUpdate 事件被触发时,Form 对象仍然不存在。我想一个 hacky 方法是在第二个线程中添加 Thread.Sleep(100) ,但我不喜欢那样。我该如何解决这个问题?我是在完全错误的轨道上吗? (我说得有道理吗?)

        Form1 theForm = new Form1();
        CreateReport theCreateReport = new CreateReport();
        Thread t = new Thread(new ThreadStart(theCreateReport.DoProcess));
        t.IsBackground = true;
        theForm.Subscribe(theCreateReport);
        t.Start();
        Application.Run(theForm);

theForm 是表单。 theCreateReport 是我的业务逻辑开始的地方。

【问题讨论】:

    标签: c# winforms multithreading


    【解决方案1】:

    您想使用一个或多个BackgroundWorker 对象而不是您的业务逻辑线程。这将为您管理线程,并为您提供一种向主线程提供进度反馈的方法。

    【讨论】:

    • 这与从 Form1() 方法中启动我的线程有何不同?我已经有了我的处理程序和代表。从表单中开始/执行所有业务逻辑是一种好的编程习惯吗?就像我提到的那样,我是一个完整的新手。谢谢。
    • 如果你已经有了一些工作,那么一定要使用它。 BackgroundWorker 只是为您提供了一种简单的方法,可以将离散任务交给另一个线程并在以后获取结果,而无需管理自己的线程。
    【解决方案2】:

    也许你应该在 OnLoad 事件中开始你的业务逻辑?

    【讨论】:

      【解决方案3】:

      在您调用构造函数后(在第一行),表单已经存在——只是还不可见。所以你不用担心,当你启动新线程时,一切都已初始化。

      【讨论】:

      • 这就是为什么我将构造函数与默认的 VC#S 项目给我的东西分开。但它似乎不起作用。给我一个错误,说我不应该在创建对象之前使用 Invoke/BeginInvoke。如果我将 try catch 块与空 catch 放在一起,它确实可以工作,但感觉就像是 hack。可能只是我太挑剔了。
      • 这是一个黑客。 .Net 中基于表单的应用程序基本上是围绕主表单的概念构建的。没有理由反对这一点,因为您的项目已经使用了主窗体。
      • 将此标记为答案,因为正如 Poma 所提到的,该表单确实已经存在。错误出现在我代码的不同部分。谢谢。
      【解决方案4】:

      Main 中,只需创建表单并Application.Run 它。在表单的Load 事件中,启动您的线程。

      按照目前的方式做事并没有真正获得任何优势。正如您已经发现的那样,它会产生时间/顺序问题。

      解决问题的最佳方法是从一开始就不存在这些问题。

      【讨论】:

      • 有人告诉我,将 GUI 和业务逻辑完全解耦是一种很好的做法。 (而不是从 GUI 方法中启动业务逻辑线程。)不过,这确实来自与我一起工作的 Java 开发人员。所以我不知道它是否适用于C#编码的情况。
      • GUI 和业务逻辑的分离更多地与代码的组织方式有关,而不是与运行不同对象的线程有关。一般来说,多线程应用程序的可靠性不如单线程应用程序,因为通过代码的路径受线程调度程序的控制,因此难以预测。有正当的理由需要多线程的固有风险(如果你知道自己在做什么,可以安全地做到这一点的),但符合 3 层正统观念确实不是'其中之一。
      【解决方案5】:

      我会使用 BackgroundWorker,您仍然可以使用您的事件和委托。这一次,您将结束并触发 Background Worker 的“ProgressChanged”和“RunWorkerCompleted”事件。

      您的 Form 可以监听这些事件并相应地更新 ProgressBar。

      BWorker 可以更好地处理切换到 GUI 线程和异常处理。

      您可以在表单加载时初始化 BackgroundWorker。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多