【问题标题】:Update a form in parallel with an installation script?与安装脚本并行更新表单?
【发布时间】:2017-06-08 20:05:44
【问题描述】:

我目前有一个执行特定操作的安装“框架”。我现在需要做的是能够与我的脚本并行调用我的表单。像这样的:

InstallationForm f = new InstallationForm();
Application.Run(f);
InstallSoftware(f);

private static void InstallSoftware(InstallationForm f) {
    f.WriteToTextbox("Starting installation...");
    Utils.Execute(@"C:\temp\setup.msi", @"-s C:\temp\instructions.xml");

    ...

    f.WriteToTextbox("Installation finished");

目前我可以做到这一点的方法是在InstallSoftware 中添加Form.Shown 处理程序,但这看起来真的很乱。无论如何我可以做得更好吗?

【问题讨论】:

    标签: c# .net multithreading winforms parallel-processing


    【解决方案1】:

    您的代码将不起作用,因为 Application.Run(f) 直到表单关闭后才会返回。

    您可以使用简化的模型/视图/控制器模式。创建一个具有多个事件的 InstallationFormController 类,例如用于将文本通知写入您的文本框。 InstallationFormOnLoad() 方法中注册这些事件,然后调用InstallationFormController.Initialize()。该方法开始您的安装(在工作线程/任务上)。该安装回调方法会触发几个文本事件。

    InstallationForm f = new InstallationForm(new InstallationFormController());
    Application.Run(f);
    
    internal class InstallationFormController
    {
      public event EventHandler<DataEventArgsT<string>> NotificationTextChanged;
    
      public InstallationFormController()
      {
      }
    
      public void Initialize()
      {
        Task.Factory.StartNew(DoInstallation);
      }
    
      private void DoInstallation()
      {
        ...
    
        OnNotificationTextChanged(new DataEventArgsT<string>("Installation finished"));
      }
    
      private void OnNotificationTextChanged(DataEventArgsT<string> e)
      {
        if(NotificationTextChanged != null)
          NotificationTextChanged(this, e);
      }
    }
    
    public class DataEventArgsT<T> : EventArgs
    {
      ...
      public T Data { get; set; }
    }
    
    internal class InstallationForm : Form
    {
      private readonly InstallationFormController _controller;
    
      public InstallationForm()
      {
        InitializeComponent();
      }
    
      public InstallationForm(InstallationFormController controller) : this()
      {
        if(controller == null)
          throw new ArgumentNullException("controller")
    
        _controller = controller;
      }
    
      protected override void OnLoad(EventArgs e)
      {
        base.OnLoad(e);
    
        _controller.NotificationTextChanged += Controller_NotificationTextChanged;
        _controller.Initialize();
      }
    
      protected virtual void Controller_NotificationTextChanged(object sender, DataEventArgsT<string> e)
      {
        if(this.InvokeRequired)
        { // call this method on UI thread!!!
          var callback = new EventHandler<DataEventArgsT<string>>(Controller_NotificationTextChanged);
          this.Invoke(callback, new object[] {sender, e});
        }
        else
        {
          _myTextBox.Text = e.Data;
        }
      }
      ...
    }
    

    【讨论】:

      猜你喜欢
      • 2016-07-02
      • 2019-11-24
      • 2023-01-20
      • 1970-01-01
      • 1970-01-01
      • 2018-05-28
      • 2014-03-15
      • 2015-11-18
      • 1970-01-01
      相关资源
      最近更新 更多