将函数中的内容返回给BGC#

将函数中的内容返回给BGC#,c#,multithreading,forms,C#,Multithreading,Forms,编辑以便更好地理解 我有一个Form1.cs文件和一个单独的Class.cs文件 在Form1中,我有一个bgWorker调用Class.myFunc(),它对每个循环执行三个foreach循环,每个循环返回一些值,例如string ClientName或string ClientOrder 我想将这些值从Class.myFunc返回给bgWorker(请记住,bgWorker位于表单1中),并将它们插入ListView、Textbox或其他任何内容 所以问题是:如何将Class.myFunc中

编辑以便更好地理解

我有一个Form1.cs文件和一个单独的Class.cs文件

Form1
中,我有一个bgWorker调用Class.myFunc(),它对每个
循环执行三个
foreach
循环,每个循环返回一些值,例如
string ClientName
string ClientOrder

我想将这些值从Class.myFunc返回给bgWorker(请记住,bgWorker位于
表单1
中),并将它们插入ListView、Textbox或其他任何内容

所以问题是:如何将Class.myFunc中的字符串值返回给BgWorker

我希望有人能帮我这个

表格1.cs

void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    ControlsHelper.ControlInvike(listProcess, () => listProcess.Items.Add("Current").Name = "item1");
            myOtherClass cp = new myOtherClass();
            cp.myFunc();
}
C类

public void myFunc()
{
    foreach (string Client in Clients)
    {
           // Do something
           // Return Client and insert into listview, richtextbox, W/E
    }
} 

您可以(ab)使用它,并将值作为第二个参数传递。

首先,确保您确实需要多线程。在列表加载完成之前,您可能只需要阻止GUI更新,就可以轻松地完成更新

如果您确实需要多线程,请确保您的三个循环需要按该顺序运行。如果没有,那么您需要3个BGWorker,而不是1个


最后,有很多关于线程安全的好文章。您将发现无法直接更新ListView,您必须使用线程安全委托。

扩展Daniel Hilgarth的回答:如果BGW在
Class.cs
的上下文中不存在,您能否将其作为参数传递,以便更新进度。在您的DoWork签名中,
对象发送方
是您要转换为BackgroundWorker以发送到
myFunc
的BGW

所以你应该

public void myFunc(BackgroundWorker bgw)
{
    foreach (string Client in Clients)
    {
       // Do something
       // Return Client and insert into listview, richtextbox, W/E

       var returningObjects = List<string>();  //I assume this will be a list of strings based on your question.
       returningObjects.Add(ClientName);
       returningObjects.Add(ClientOrder);
       returningObjects.Add(Client3rdThing);

       bgw.ReportProgress(0,returningObjects)
    }
} 
然后在ProgressChanged事件处理程序中

private void bgWorker_ProgressChanged(object sender,
    ProgressChangedEventArgs e)
{
   //Set the  e.UserState to whatever you need. It is of type Object.
    var returnedObjects = e.Userstate as List<string>;
    if(returnedObjects != null)
    {
        //do stuff with each of your returnedObjects[i];
    }

}

听起来您可以将“listview”传递到函数中,让函数插入值。@Sam.Rueby:不起作用,因为BackgroundWorker运行在与UI线程不同的线程上。@DanielHilgarth噢-这个问题很难理解。我已经编辑了这个问题,我希望现在很容易理解,因为据我所知,我无法从其他类文件访问BackgroundWorker.ReportProgress,因为它在当前上下文中不存在…@user1381537:这句话很难理解。请使用一些示例代码编辑您的问题。完成后,我使用bgworker dowork代码和myfunc代码进行了编辑。我正在使用安全委托,我已经为此创建了一个类和函数。我需要多线程,它必须是3个循环,一个循环在另一个循环中,另一个循环在另一个循环中,必须是这样,我已经用其他语言做过了,但不是C#和多线程。按照你解释的方式,myFunc方法与bgWorker在同一个线程上运行。要将值返回给bgWorker,只需将返回类型设置为string或List,而不是void。这一部分很简单,与从bgWorker获取GUI组件的值相比。谢谢,这正是我想要的。。。但我有一个问题,如何将e.UserState作为数组返回?我有三个值要插入到listview中,如何使用e.UserState[0]-e.UserState[1]-e.UserState[2]查看我的更新。只需知道您可以通过
UserState
对象传递任何内容,因为它属于
object
类型。使用时一定要适当地进行转换。抱歉,我将它变成了
List
而不是
Array
但我认为您得到了这个想法。是的,这实际上是我做的,它起到了作用;)但我有和一开始一样的问题。。。ListView为myfunc上的每个foreach添加一行。。。它必须只有一行,在myFunc运行时更新元素,不添加新行><
if(obj!=null){ControlExtension.ThreadSafeInvoke(listProcess,()=>listProcess.Items.Add(“项标题”).SubItems.AddRange(obj));}
hmmm您是否能够手动将您的
obj
添加到您的listview?i、 你能做一个小的测试方法来做所有这些必要的事情而不需要线程的复杂性吗?如果您可以将它添加到那里,那么将它移植到这个线程场景应该很容易。除此之外,我还需要有Visual Studio在我面前(我现在没有)
private void bgWorker_ProgressChanged(object sender,
    ProgressChangedEventArgs e)
{
   //Set the  e.UserState to whatever you need. It is of type Object.
    var returnedObjects = e.Userstate as List<string>;
    if(returnedObjects != null)
    {
        //do stuff with each of your returnedObjects[i];
    }

}
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);