C# 尽管设置了ApartmentState,但仍存在跨线程错误

C# 尽管设置了ApartmentState,但仍存在跨线程错误,c#,multithreading,C#,Multithreading,我正在尝试向我的UI显示循环的内容。首先,我不确定我是否以正确的方式(使用WinForms)实现了这一点,但这就是我正在做的: foreach (string item in stringArray) { Thread thread = new Thread(delegate() { UpdatedResultEvent(item);

我正在尝试向我的UI显示循环的内容。首先,我不确定我是否以正确的方式(使用WinForms)实现了这一点,但这就是我正在做的:

foreach (string item in stringArray)
{
        Thread thread = new Thread(delegate()
                              {
                                  UpdatedResultEvent(item);
                              });
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
}
我希望这是足够的信息,但如果不是这样,我将在这里详细介绍

我有两个类,我的Program.cs(WinForm)和另一个名为logicClass的类。我将程序对象的实例传递给logicClass。我的logicClass有一个委托,其签名与程序类中的方法匹配。作为委托传递的方法是

public void UpdateResultsOnScreen(string newContent)
{
txtResults.Text += newContent;
}
错误消息是

跨线程操作无效:从线程访问控件 而不是创建它的线程

编辑


与进度条的工作方式类似,目标是看到控件实时更新。目前,即使它确实工作,线程也不会将“结果”返回到屏幕,直到线程完成

即使您正在设置ApartmentState,也必须在从另一个(非UI)线程访问时调用UI控件

确保在UpdateResultEvent方法中调用UI控件

不管怎样,你所做的不是一个好主意,考虑使用一个或“/P>”。 它会自动扩展您的代码,产生大量线程会降低性能,特别是当您的集合中包含大量项目时。

使用此选项(如果您使用WinForms):

public void UpdateResultsOnScreen(字符串newContent)
{
txtResults.BeginInvoke(
新操作((值)=>
{
txtResults.Text+=值;
}),
新内容);
}

也如<强> iNoMAial所说,考虑使用<代码>线程池> />代码>或<代码>并行。p>

 public void UpdateResultsOnScreen(string newContent)
    {
        if(txtResults.InvokeRequired)
        {
            txtResults.Invoke(
                new Action<string>(content => txtResults.Text += content), newContent);
            return;
        }
        txtResults.Text += newContent;
    }
public void UpdateResultsOnScreen(字符串newContent)
{
if(txtResults.InvokeRequired)
{
txtResults.Invoke(
新操作(content=>txtreults.Text+=content),newContent;
返回;
}
txtResults.Text+=新内容;
}

这真的很好,但它不会在屏幕上实时显示我的结果。我的文本框仍然一次显示所有内容,而不是一次填充一个项目。例如,假设每次调用UpdatedResultEvent(项)都需要5秒钟(由于数据库/Web服务调用等原因)。这意味着我希望我的屏幕每5秒钟更新一次。@DaveRook请尝试我编辑的代码。我认为,即使是旧代码(
Invoke
)也应该像您所期望的那样工作并更新UI,但是如果它不工作,我们需要知道您是如何准确地完成它的。我想这应该是另一个问题。是的,我已经用BeginInvoke()尝试过了,但结果相同。如果你认为这应该是可行的,那么也许我的设计中还有其他地方是错误的@大卫:是的,我认为它应该会起作用。通过使用单独的线程,您不会阻塞UI线程。通过使用
Invoke
BeginInvoke
方法,您将向UI发送一条消息,并告诉它进行自我更新。因此,它应该可以工作,除非您以其他方式阻止UI,比如使用
thread.Join()
。不,不使用thread.Join,也不睡眠线程。嗯,一定是我的密码错了。非常感谢。
 public void UpdateResultsOnScreen(string newContent)
    {
        if(txtResults.InvokeRequired)
        {
            txtResults.Invoke(
                new Action<string>(content => txtResults.Text += content), newContent);
            return;
        }
        txtResults.Text += newContent;
    }