从另一个类写入文本框(在另一个线程上)

时间:2013-02-08 20:35:21

标签: c# .net winforms multithreading class

我需要在我的程序中创建一个类来启动一系列事件来在文本框中编写文本。 我知道课程不应该知道表格。怎么做?考虑到我将在另一个线程上安装该类的事实。

我已经尝试使用ref参数创建一个连接类和make方法的接口。

* 更新: *你们都误解了我 - 我在谈论的事件不是在进行程序设计。我需要的是从另一个类添加文本到文本框。我添加了“事件链”来从simila问题中定义它,在其中他们试图从课堂上直接改变文本。遗憾。

2 个答案:

答案 0 :(得分:4)

这里有两种可能的选择:

“其他类”需要在文本框“完成”后立即更新文本框。如果是这种情况,它应该永远不会知道表单,任何文本框,界面,什么都不知道。它应该返回一个值并让表单使用该返回值来设置文本框,或者做任何事情。

在大多数情况下,这是您想要做的,而且它是解决此类问题的最简单,最有效的方法。如果你不需要,不要使用更复杂的东西。

如果在任务“完成”时没有发生信息,而是通过定期间隔,那么您可以将Progress类与IProgress接口一起使用。

Form创建一个实例:Progress<string> progress = new Progress<string>();。让表单附加该实例的事件处理程序。请注意,Progress实例将“捕获”当前的同步上下文,这是一种说它在UI线程中运行的奇特方式。这可以这样做:

progress.ProgressChanged += (_, data) => textBox1.Text = data;

然后让其他类接受IProgress<string>实例并定期调用:

progress.Report(someString);

如果您需要4.5之前的ProgressIProgress实现,这是一个将在.NET 3.5 +中编译和运行的实现:

public interface IProgress<T>
{
    void Report(T data);
}

public class Progress<T> : IProgress<T>
{
    SynchronizationContext context;
    public Progress()
    {
        context = SynchronizationContext.Current
            ?? new SynchronizationContext();
    }

    public Progress(Action<T> action)
        : this()
    {
        ProgressReported += action;
    }

    public event Action<T> ProgressReported;

    void IProgress<T>.Report(T data)
    {
        var action = ProgressReported;
        if (action != null)
        {
            context.Post(arg => action((T)arg), data);
        }
    }
}

答案 1 :(得分:2)

如果不了解您的应用程序,我会建议您需要调用由表单处理的类中的事件。会发生什么是这样的:

  1. 班级有活动。
  2. 表单启动并实例化类。
  3. 表单为类中的事件指定处理程序。
  4. Class会做任何需要做的事情,直到它达到需要与表单通信的程度。
  5. Class举起活动。
  6. 执行表单中的处理程序并更改文本框。
  7. 因此,在类的代码中,您需要添加一些定义:

    public delegate void FinishedEventHandler(object sender, string ValueToReturn);
    public event FinishedEventHandler Finished;
    

    第一个是具有事件的签名的代表。按照惯例,第一个参数始终是对类本身实例的引用,其余的是您要返回的值。第二个是实际的事件。

    现在,在执行任何处理类的函数中,我们需要在适当的时候引发事件:

    void DoSomething()
    {
        .
        .
        .
        if(Finished!=null) Finished(this, "some value");
    }
    

    if子句用于确保某人实际处理我们的事件,否则我们可能会遇到异常。

    现在让我们来看一下表格。我们需要添加一个处理事件的函数。它需要与我们之前定义的委托具有相同的签名。在该函数中,我们根据我们得到的值对表单进行任何改变:

    private void FinishedEventHandler(object sender, string ValueToReturn)
    {
        TextBox1.Text = ValueToReturn;
    }
    

    现在我们已经准备好使用我们刚创建的所有管道。首先,我们将处理程序添加到事件中,然后我们可以调用类的处理函数。

    MyClass.Finished += FinishedEventHandler;
    MyClass.DoSomething();
    

    这是一个更详细的教程:

    http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx