English 中文(简体)
C#GUI班如何从工人班得到定期更新?
原标题:How a C# GUI class receive periodic updates from a worker class?

我试图将我的工作代码从我的 GUI 代码中分离成完全不同的类别, 但我想能够向我的 GUI 报告进度更新和文件输出。 例如, 我想让我的 GUI 对工人阶级说 : “ 从序列端读取十行, 但只要你收到, 就会向我报告你读到的每件事。 ”目前我最好的方法就是让 GUI 循环十次, 在每个循环中向工人阶级发送命令, 读一个东西, 然后把它还回去 。

我很想把所有环绕在工人阶级的侧面, 因为它会有更多关于现有数据的信息(数据的实际数量是可变的, 工人阶级已经可以获取现有数据的数量,

我调查过背景工作者,但这似乎只是报告在长期行动期间完成的百分比,除此之外没有任何其他结果,因此这对我在这里没有多大帮助。 有没有人知道我如何能够完成这个任务?

下面是一个程序外壳, 试图( 希望) 更好地说明我想做什么。 您将如何编辑代码来完成我所要求的任务?

图形用户界面主类 :

class Main_Class
{
    ...
    /*  Assume in the area we have instantiated these items and placed them on the form:
    *   Button  DoSomething:  A button to do something
    *   TextBox ShowInfo:  A text box to report something from the worker class     
    */

    Worker_Class timewaster = new Worker_Class();

    private void buttonDoSomething_Click(object sender, EventArgs e)
    {
        timewaster.a_lengthy_task();
    }
}

单独的工人类别:

class Worker_Class
{
    ...//Various Setup stuff up here

    void a_lengthy task()
    {
        int iteration = 0;

        while(iteration < 10)
        {
            Datetime saveNOW = Datetime.Now;        //lets say I report this back to the the GUI to write in that ShowInfo box
            Thread.sleep(10000);                    //To waste time and make this lengthy

            //Your code here to facilitate sending saveNOW back to the the Main_Class and display it on the ShowInfo textbox.

            iteration++
        }
    }
}
最佳回答

您需要的是事件。如果您无法围绕 Backflorkworker 类中构建的内容工作,使其为您工作,您至少可以按照它的工作模式模拟自己的解决方案。

工人类应该有一个公共事件 < code> IterationCompllete 或任何你想称之为它的东西。 您可以给它一个 < code> EventArgs 对象( 或一个延长事件Args的对象), 其中包含与UI需要的迭代相关的信息。 该事件可以在每次迭代完成后( 或每当UI修改完成时) 发射 。

用户界面然后可以订阅与该迭代有关的所有用户界面任务的事件。

代码样本 :

主类 :

public class MainClass
{
    Worker_Class timewaster = new Worker_Class();


    private void buttonDoSomething_Click(object sender, EventArgs e)
    {
        timewaster.IterationComplete += new EventHandler<Worker_Class.IterationEventArgs>(timewaster_IterationComplete);
        timewaster.LengthyTask();
    }

    void timewaster_IterationComplete(object sender, Worker_Class.IterationEventArgs e)
    {
        string infoFromWorker = e.iterationNumber;
    }
}

工人阶级 :

public class Worker_Class
{
    //Various Setup stuff up here

    public class IterationEventArgs : EventArgs
    {
        public string iterationNumber { get; set; }
    }

    public event EventHandler<IterationEventArgs> IterationComplete;

    public void LengthyTask()
    {
        int iteration = 0;

        while (iteration < 10)
        {
            DateTime saveNOW = DateTime.Now;        //lets say I report this back to the the GUI to write in that ShowInfo box
            Thread.Sleep(10000);                    //To waste time and make this lengthy

            //Your code here to facilitate sending saveNOW back to the the Main_Class and display it on the ShowInfo textbox.

            if (IterationComplete != null)
            {
                IterationEventArgs args = new IterationEventArgs();
                args.iterationNumber = iteration.ToString();
                IterationComplete(this, args);
            }

            iteration++;
        }
    }
}
问题回答

这是 Backflorker 类的理想任务。 假设您不使用紧凑框架, 您应该可以使用它 。

Backfroundworker 上,您可以监听 on completed on Instep UI 更新 事件。 这些事件被汇集到您的 UI 线索中, 您可以安全地更新您的双形/ wpf 控制。 要显示进度, 您在 ReportReportRest() 内, 您会调用 DoWork () 的 < backfroomworker 。

当将代码带入单独的线索时,您在更新 GUI 控件时需要小心。作为更新控件的线索,必须是 UI 线索。背景工作员会为您处理此事宜。

MSDN - < a href=>http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx" rel="nofollow">http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

您需要将您的 Worker_Class_Class 通过事件广播其进度。 < code> main_Class 将订阅此事件, 并使用此信息对 UI 进行相应更新。 您可以从这里分到两个方向。 您可以使用 < code> control. Invoke 将此事件处理器调到 UI 线索上, 以便安全更新 GUI 。 或者您可以让事件处理器将进度信息保存到共享变量中。 然后, 您的 UI 会通过 < code> System. Windows. Forms.Timerr 或 < code > DispatcherTimer 在方便的间隔上调这个变量。 我更愿意在此情况下采用较晚的方法 。

class YourForm : Form
{
  private volatile MyEventArgs progress = null;

  private void buttonDoSomething_Click(object sender, EventArgs args)
  {
    var timewaster = new Worker_Class();
    timewaster.ProgressChanged += (sender, args) { progress = args; };
    Task.Factory.StartNew(
      () =>
      {
        timewaster.a_lengthy_task();
      }
    UpdateTimer.Enabled = true;
  }

  private void UpdateTimer_Tick(object sender, EventArgs args)
  {
    if (progress != null)
    {
      if (progress.IsFinished)
      {
        ShowInfo.Text = "Finished";
        UpdateTimer.Enabled = false;
      }
      else
      {
        ShowInfo.Text = progress.SaveNow.Value.ToString();
      }
    }
    else
    {
      ShowInfo.Text = "No progress yet";
    }
  }
}

class Worker_Class
{
  public event EventHandler<MyEventArgs> ProgressChanged;

  public Worker_Class()
  {
    ProgressChanged += (sender, args) => { };
  }

  public void a_lengthy task()
  {
    int iteration = 0;
    while(iteration < 10)
    {
        Datetime saveNOW = Datetime.Now;
        Thread.sleep(10000);
        ProgressChanged(this, new MyEventArgs { SaveNow = saveNOW, IsFinished = false });
        iteration++
    }
    ProgressChanged(this, new MyEventArgs { SaveNow = null, IsFinished = true });
  }
}

class MyEventArgs : EventArgs
{
  public DateTime? SaveNow { get; set; }
  public bool IsFinished { get; set; }
}

在我的背景工作者中,我使用:

this.Invoke((MethodInvoker)delegate
{
    //do something in GUI
});

例如,如果您想要在 GUI 使用中更改标签

label.Text = "whatever";

方法内。





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签