Reputation: 1016
I currently have a function that populates a listview with data. This function get passed parameters.
I now want to populate the listview in a different thread from the main ui thread. However i am a little unsure how i would pass the parameters to the thread.
Upvotes: 3
Views: 8272
Reputation: 266
Old post, but here is a complete solution for anyone stumbling on this post. This allows passing parameters to a Backgroundworker, supports cancellation, and passes back information to the main thread (via ProgressChanged) where it can update the ListView. I created a solution from scratch. Tested working.
C# / .NET Framework 4.6.2 / VS2019 build 16.4.1
BackgroundWorker1 properties:
WorkerReportsProgress = True
WorkerSupportsCancellation = True
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
namespace test2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(Object sender, EventArgs e)
{
listView1.View = View.Details;
listView1.GridLines = true;
listView1.Columns.Add("Store",100);
listView1.Columns.Add("Product", 100);
listView1.Columns.Add("Price", 60);
listView1.Columns.Add("Qty", 60);
}
private void backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e)
{
if(!(e.Argument is String store)) return;
List<String> items = new List<String>();
if(backgroundWorker1.CancellationPending) {e.Cancel = true; return;}
items.Add(store);
items.Add("Bananas");
items.Add("0.79");
items.Add("50");
backgroundWorker1.ReportProgress(0, items);
}
private void backgroundWorker1_ProgressChanged(Object sender, ProgressChangedEventArgs e)
{
if(!(e.UserState is List<String> resultitems)) return;
ListViewItem itm = new ListViewItem(resultitems.ToArray());
listView1.Items.Add(itm);
}
private void backgroundWorker1_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e)
{
//Do any final cleanup once backgroundworker is complete
}
private void button1_Click(Object sender, EventArgs e)
{
if(backgroundWorker1.IsBusy)
{
backgroundWorker1.CancelAsync();
return;
}
backgroundWorker1.RunWorkerAsync("Glendale");
}
private void button2_Click(Object sender, EventArgs e)
{
if(backgroundWorker1.IsBusy)
{
backgroundWorker1.CancelAsync();
return;
}
backgroundWorker1.RunWorkerAsync("Toledo");
}
}
}
Upvotes: 1
Reputation: 1321
It has to be passed as a parameter (object) through RunWorkAsync. Be sure to cast it to whatever you passed in.
Private Sub frm_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
bgwThread.RunWorkerAsync('your parameters here')
'e.g.:
Dim sTemp As String = "Hello"
bgwThread.RunWorkerAsync(sTemp)
End Sub
Private Sub bgWorker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles bgwThread.DoWork
Dim sThisIsYourParameter As String = CStr(e.Argument)
'...
DoStuff()
End Sub
Although as Hans said above, you can't populate the ListView in another thread. This is just "how to pass a parameter to a backgroundworker."
Upvotes: 4