C# 我可以使用后台工作线程向列表框添加值吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/368006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# Can I add values to a listbox with a backgroundwork thread?
提问by
I want my background worker to add items to a list box, it appears to do so when debugging but the listbox doesn't show the values. I suspect this is something to do with adding items whilst inside the background worker thread, do I need to add these to an array and then populate the list box from the array during backgroundWorker1_RunWorkerCompleted
?
我希望我的后台工作人员将项目添加到列表框中,调试时似乎这样做,但列表框不显示值。我怀疑这与在后台工作线程内添加项目有关,我是否需要将这些添加到数组中,然后在此期间从数组填充列表框backgroundWorker1_RunWorkerCompleted
?
Thanks for the help.
谢谢您的帮助。
回答by Quibblesome
You can add them while on a background thread via:
您可以通过以下方式在后台线程中添加它们:
Form.Invoke
or
或者
Form.BeginInvoke
which are required to marshall the call from a background thread to a main UI thread. However I'm pretty sure BackgroundWorker offers an event that automatically gets called on the Foreground thread and you should be able to update on this event without any problems. This is "ProgressChanged" which can be fired by the background worker process by calling ReportProgress.
需要将调用从后台线程编组到主 UI 线程。但是,我很确定 BackgroundWorker 提供了一个在 Foreground 线程上自动调用的事件,您应该能够毫无问题地更新此事件。这是“ProgressChanged”,它可以通过调用 ReportProgress 由后台工作进程触发。
Have you tried calling .Refresh()
on the listbox as well?
您是否也尝试过调用.Refresh()
列表框?
回答by Oliver Friedrich
You can, but you must advise your Backgroundworker to report state, and send the input for the box with the current state to that event. In the method for that event, you can access the box and put the new value in.
您可以,但您必须建议您的后台工作人员报告状态,并将具有当前状态的框的输入发送到该事件。在该事件的方法中,您可以访问该框并将新值放入。
Otherwise you need to invoke manually.
否则,您需要手动调用。
public Form1()
{
InitializeComponent();
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync();
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10; i++)
{
((BackgroundWorker)sender).ReportProgress(0, i.ToString());
}
}
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
listBox1.Items.Add((string)e.UserState);
}
回答by Gonzalo Quero
You can use Invoke like this:
您可以像这样使用 Invoke:
private void AddToListBox(object oo)
{
Invoke(new MethodInvoker(
delegate { listBox.Items.Add(oo); }
));
}
回答by Marcus Erickson
I add functions like the following so that I can add items to the list box from either the main thread or background threads. Thi thread checks if a Invoke is necessary and then uses Invoke if it is necessary.
我添加如下函数,以便我可以从主线程或后台线程向列表框添加项目。Thi 线程检查是否需要调用,然后在需要时使用调用。
delegate void AddListItemDelegate(string name,object otherInfoNeeded);
private void
AddListItem(
string name,
object otherInfoNeeded
)
{
if (InvokeRequired)
{
BeginInvoke(new AddListItemDelegate(AddListItem), name, otherInfoNeeded
return;
}
... add code to create list box item and insert in list here ...
}
回答by Abdul Hameed
Application.Doevents()
function will solve the problem.
Application.Doevents()
函数将解决问题。
回答by Michael Smith
if you are trying to update a database. From a listbox i would suggest creating a dataset.
如果您正在尝试更新数据库。从列表框中,我建议创建一个数据集。
for instance, if your doing something for each item in a database. Copy the database dataset, by creating new dataset and declaring by mainDataset.
例如,如果您为数据库中的每个项目做某事。通过创建新数据集并通过 mainDataset 声明来复制数据库数据集。
for example: // the gridview dataset is dataset1
例如:// gridview数据集是dataset1
BackgroundWorker_DoWork(object sender, DoWorkArgs e)
{
Dataset dataset2 = dataset1;
foreach(DataGridViewRow row in GridView)
{
//do some work
dataset2.Main.AddMainRow(values to add);
dataset2.AcceptChanges();
}
}
BackgroundWorker_WorkCompleted(object sender, DoWorkArgs e)
{
//Forces UI thread to valitdate dataset
dataset2.update();
// Sets file Path
string FilePath = "Some Path to file";
dataset2.writexml(FilePath, XmlWriteOptions.WriteSchema);
//if you use xml to fill your dataset filepath to write should equal path to dataset1 xml
dataset1.Refresh();
}