Ok, in my app there are times when loading the DataGridView can take a minute or two. What I want to do is show a GIF in a form with no border until it reaches the end of the loading function. However, if I do:
Views.Loading ldw = new Views.Loading();
ldw.Show();
...
ldw.Close();
...it never actually draws it to the screen and I can't see it. If I do ShowDialog(), it shows the window but never gets past that line of code. I have a feeling it's because it's not a background worker or because the focus gets set back to the parent because of processing...I don't know.
My form is a blank form, added a picture box, added a gif to the picture box, and made FormBorderStyle = none. Any and all help is appreciated.
Update: Current (non-working) Code
private void InitializeBackgroundWorker()
{
//Defines the DoWork Event Handler for _backgroundWorker.
_bgWorkerReports.DoWork += new DoWorkEventHandler(bgWorkerReports_DoWork);
//Defines the RunWorkCompleted Event Handler for _backgroundWorker.
_bgWorkerReports.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorkerReports_RunWorkerCompleted);
}
private void bgWorkerReports_DoWork(object sender, DoWorkEventArgs e)
{
ldw.Show();
try
{
string strFilter = "";
if (!_strSearchFilter.Equals(""))
{
strFilter += strFilter.Equals("") ? " " + _strSearchFilter : " and " + _strSearchFilter;
}
if (tvFigure.Nodes.Count > 0)
{
if (_strFigureFilter == "ALL")
{
strFilter += " " + Constants.GetColumnName("Figure") + " LIKE '%%' ";
}
else if (!_strFigureFilter.Equals("") && !_strFigureFilter.Equals(tvFigure.TopNode.Name))
{
if (_strSearchFilter.Equals("") || !cbCurrentFigure.Checked)
{
strFilter += strFilter.Equals("") ? " " + Constants.GetColumnName("Figure") + "='" + _strFigureFilter + "'" : " and " + Constants.GetColumnName("Figure") + "='" + _strFigureFilter + "'";
}
}
}
if (!_strIndentureFilter.Equals(""))
{
strFilter += strFilter.Equals("") ? " " + _strIndentureFilter : " and " + _strIndentureFilter;
}
if (!_strReportFilter.Equals(""))
{
strFilter += (!strFilter.Equals("") ? " and" : "") + " part_id in (" + _strReportFilter + ")";
}
if (strFilter.Length > 0)
{
BindingSource bSource = new BindingSource();
bSource.DataSource = _dataController.PopulateDataGrid(_nViewMode, strFilter).Tables[0];
//Set DataSource to bindingSource for DataGridView.
if (_lstValidationResults.Count > 0)
{
dgvParts.DataSource = _lstValidationResults;
foreach (DataGridViewColumn dc in dgvParts.Columns)
{
dc.DataPropertyName = "ErrorMessage";
dc.Visible = true;
dc.SortMode = DataGridViewColumnSortMode.Programmatic;
dc.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;
}
dgvParts.AutoResizeColumns();
return;
}
else if (!string.IsNullOrEmpty(_strFigureFilter))
{
dgvParts.DataSource = bSource;
dgvParts.Columns[0].Visible = false;
dgvParts.Columns["Description"].Resizable = DataGridViewTriState.False;
dgvParts.Columns["Description"].Width = 750;
}
// Automatically resize the visible rows.
foreach (DataGridViewColumn col in dgvParts.Columns)
{
col.SortMode = DataGridViewColumnSortMode.Automatic;
if (col.Name != "Description")
{
dgvParts.AutoResizeColumn(col.Index);
}
}
dgvParts.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells;
// Hide the ToolTips for all the cells - redisplay if there is a report.
dgvParts.ShowCellToolTips = true;
// Set the dataGridView control's border.
dgvParts.BorderStyle = BorderStyle.Fixed3D;
// Get and set the ipb_number to the label.
string ipb_number = _dataController.IPBNumber;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void bgWorkerReports_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
ldw.Close();
this.Cursor = Cursors.Default; //Throws error (Cross-thread)
FormatCells();
BuildColumnsComboBox();
int nTotalCount = 0;
foreach (ListViewItem lvi in listView1.Items)
{
int nCount = _lstReportRecords.Where(rr => lvi.Text.Contains(rr.Description)).Count();
nTotalCount += nCount;
lvi.Text = (lvi.Text.Contains("(") ? lvi.Text.Substring(0, lvi.Text.IndexOf("(") + 1) : lvi.Text.Trim() + " (") + nCount.ToString() + ")";
}
rbAllReports.Text = (rbAllReports.Text.Contains("(") ? rbAllReports.Text.Substring(0, rbAllReports.Text.IndexOf("(") + 1) : rbAllReports.Text + " (") + nTotalCount.ToString() + ")";
int nTaggedCount = _lstReportRecords.Where(rr => rr.Description.Contains("Tagged")).Count();
rbTaggedRecords.Text = (rbTaggedRecords.Text.Contains("(") ? rbTaggedRecords.Text.Substring(0, rbTaggedRecords.Text.IndexOf("(") + 1) : rbTaggedRecords.Text + " (") + nTaggedCount.ToString() + ")";
}
Ideally you would have two threads: the GUI thread and the working thread (which can be a BackgroundWorker). Create and show the window in the GUI thread. Handle the loading in the BackgroundWorker's DoWork event. When the loading is done you can call Close() on the load window from the RunWorkerCompleted event and dispose of it.
LoadWindow loadWindow = new LoadWindow();
loadWindow.TopMost = true; // make sure it doesn't get created behind other forms
loadWindow.Show();
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
void worker_DoWork(object sender, DoWorkEventArgs e)
{
// do your loading here
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// set DataGridView datasource here
...
// close loading window
loadWindow.Close();
}
The problem you might have with displaying the window could be from the TopMost property, which must be set to true. You can also try calling BringToFront() on the loading window after you've created and shown it.
Yes, BackgroundWorker is for exactly this type of purpose. A couple things to add:
Do not interact with the UI in the worker_DoWork event as it is running on a background thread. Set e.Result when you're finished, which you can check from the RunWorkerCompleted event - or use a form-level variable.
Let any exceptions fall through in the worker_DoWork event and you will see them in the worker_RunWorkerCompleted event in e.Error.
If you need the ability to cancel your load, set worker.WorkerSupportsCancellation and check the e.Cancel while in your DoWork event, then you can check e.Cancelled in your RunWorkerCompleted event.
You should call .Dispose() on your BackgroundWorker when finished.
You'll have to run the code to fill the grid on another thread. Something like:
// Set the picturebox loading state, resize the form etc.
PictureBox.SetLoadingImage();
// Initialize a new thread
Thread t = new Thread(new ThreadStart(() =>
{
// Fill the gridview here
GridView1.DataSource = FillWithData();
GridView1.DataBind();
// When finished, reset the picturebox on it's own thread
PictureBox.Invoke((MethodInvoker)(()=> PictureBox.ClearLoadingImage() ));
}));
// Run the thread.
t.Start();
Related
I started coding my first WPF app and I'm having trouble with a textbox that displays some system info (cpu, memory, disk usage, mac address, etc.).
My apps has navigation between two pages and the said textbox is on one of the pages. The textbox's content is retrieved via WMI queries.
The issue I have noticed is that while navigating to tha page with the textbox it freezes the UI for about two seconds before going to and display the page.
I'm a newbie and my best guess is that eighter the WMI queries(could be badly coded too) are doing that or I'm loading the content in the textbox wrongfully.
An example of how my queries are constructed
public string getCPU()
{
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_Processor");
StringBuilder sb = new StringBuilder();
foreach (ManagementObject wmi in searcher.Get())
{
try
{
sb.Append("Processor: " + wmi.GetPropertyValue("Name").ToString() + Environment.NewLine);
}
catch
{
return sb.ToString();
}
}
return sb.ToString();
}
public string getRAMsize()
{
ManagementClass mc = new ManagementClass("Win32_ComputerSystem");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject item in moc)
{
return Convert.ToString(Math.Round(Convert.ToDouble(item.Properties["TotalPhysicalMemory"].Value) / (1024 * 1024 * 1024), 0)) + " GB";
}
return "RAMsize";
}
And this is what I use to retrieve the data in the textbox:
private void TextBox1_Loaded(object sender, RoutedEventArgs e)
{
TextBox1.Text = getCPU();
TextBox1.Text += "Memory: " + getRAMsize() + Environment.NewLine;
TextBox1.Text += "Free Space: " + GetTotalFreeSpace(sysdrive) + " GB" + Environment.NewLine;
if (Is64BitSystem)
{
TextBox1.Text += getOS() + " 64bit" + Environment.NewLine;
}
else
{
TextBox1.Text += getOS() + " 32 Bit" + Environment.NewLine;
}
TextBox1.Text += "MAC Address : " + System.Text.RegularExpressions.Regex.Replace(GetMacAddress().ToString(), ".{2}", "$0 ") + Environment.NewLine;
TextBox1.Text += av();
}
My question is what am I doing wrong and how can I get around with it. In my mind , if the queries are constructed correctly, it would be because they are done again and again everytime the textbox is loaded (on navigation or at startup) and maybe If I could get it to load only once and remember those values(since most of the data should stay the same).
But as I said I'm a noob and any help will be greatly appreciated.
Thanks in advance
You are aquiring your data in the UI Thread.
You should load the data in the background thread and then, since you use wpf, binding the textbox text to a variable.
Example (This code is Copy'n'Paste ready):
// INotifyPropertyChanged is an Interface which enables binding of Properties in your window
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string _systemInformation;
// Stub (works actually)
private bool is64BitSystem = (IntPtr.Size == 8);
// Stub
private string sysdrive = "YOLO\\:";
public MainWindow()
{
InitializeComponent();
// Set Datacontext normally set to a viewmodel but ther is none in this code
this.DataContext = this;
// The Backgroundworker does things in the background (nonblocking)
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += DoItButDontInterruptMeDuh;
bw.RunWorkerAsync();
}
public event PropertyChangedEventHandler PropertyChanged;
public string SystemInformation { get => _systemInformation; set => _systemInformation = value; }
//Stub
public string getCPU()
{
return "Fancy CPU";
}
//Stub
public string getRAMsize()
{
return "1 PB";
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
//Stub
private string av()
{
return "Whatever av means.";
}
private void DoItButDontInterruptMeDuh(object sender, DoWorkEventArgs e)
{
// Simulate loading time
Thread.Sleep(5000);
SystemInformation = getCPU();
SystemInformation += "Memory: " + getRAMsize() + Environment.NewLine;
SystemInformation += "Free Space: " + GetTotalFreeSpace(sysdrive) + " GB" + Environment.NewLine;
if (is64BitSystem)
{
SystemInformation += getOS() + " 64bit" + Environment.NewLine;
}
else
{
SystemInformation += getOS() + " 32 Bit" + Environment.NewLine;
}
SystemInformation += "MAC Address : " + System.Text.RegularExpressions.Regex.Replace(GetMacAddress().ToString(), ".{2}", "$0 ") + Environment.NewLine;
SystemInformation += av();
OnPropertyChanged("SystemInformation");
}
//Stub
private object GetMacAddress()
{
return "Macintoshstreet 1234";
}
//Stub
private string getOS()
{
return "Cool OS";
}
//Stub
private string GetTotalFreeSpace(object sysdrive)
{
return "0";
}
}
and in the .xaml:
<TextBox Text={Binding Path=SystemInformation}/>
After checking each and every query I found out that the getCPU one is causing a delay in the load.
I replaced it with a Registry.GetValue, wich is very fast.
Thanks to Sebastian L, because altough his code didn't work for me it put me on the right path and I was able to adapt own code with a backgroundworker to avoid UI freeze of any kind
my working code:
private void TextBox1_Loaded(object sender, RoutedEventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler(delegate (object o, DoWorkEventArgs args)
{
});
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate (object o, RunWorkerCompletedEventArgs args)
{
TextBox1.Text = (string)Registry.GetValue(#"HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0", "ProcessorNameString", null) + Environment.NewLine;
TextBox1.Text += "Memory: " + getRAMsize() + Environment.NewLine;
TextBox1.Text += "Free Space: " + GetTotalFreeSpace(sysdrive) + " GB" + Environment.NewLine;
if (Is64BitSystem)
{
TextBox1.Text += getOS() + " 64bit" + Environment.NewLine;
}
else
{
TextBox1.Text += getOS() + " 32 Bit" + Environment.NewLine;
}
TextBox1.Text += "MAC Address : " + System.Text.RegularExpressions.Regex.Replace(GetMacAddress().ToString(), ".{2}", "$0 ") + Environment.NewLine;
TextBox1.Text += av();
});
bw.RunWorkerAsync();
}
I have a problem with background worker, it gets called twice thus, increasing the time of execution for my long routine, I created background worker manually so, there is no chance for the DoWork to be initialized within the initializeComponent() method, any help is appreciated.
here is my code:
// constructor
public TeacherScheduleForm(Therapist therapist)
{
this.therapist = therapist;
InitializeComponent();
bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
bw.DoWork += bw_DoWork;
bw.ProgressChanged += bw_ProgressChanged;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
load = new LoadingForm();
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
load.AppendProgress(e.ProgressPercentage);
// load.AppendText(e.ProgressPercentage.ToString() + "%");
Console.Write("Progress: " + e.ProgressPercentage);
// MessageBox.Show("Progress : " + e.ProgressPercentage);
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
MessageBox.Show("Cancelled");
}
else if (!(e.Error == null))
{
MessageBox.Show("Error : " + e.Error);
}
else
{
updateUI();
load.Close();
Console.Write( "Done!");
}
}
// do work of background worker
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; (i <= 2); i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
Console.Write("Before Doing work");
setup(therapist.therapistID + "", schoolYear);// the time consuming operation
Console.Write("Doing work");
//System.Threading.Thread.Sleep(100);
worker.ReportProgress((i*5));
}
}
}
The background worker is called when the user selects the school year through a combo box which is in this code below:
private void comboBoxSchoolYear_SelectedIndexChanged(object sender, EventArgs e)
{
//load = new LoadingForm();
schoolYear = int.Parse(comboBoxSchoolYear.SelectedValue + "");
try{
if (!bw.IsBusy)
{
bw.RunWorkerAsync();
load.ShowDialog();
}
else
{
bw.CancelAsync();
}
}
catch(Exception ex)
{
Console.Write("Error : " + ex.Message);
}
}
You are loading the form after creating the event-handler. Thats the only point I can think off doing the trouble. Try to load the form first and then create the handler.
Reason: At InitializeComponent(); the IndexChanged normally will fire up because the control is set at this point with its index. I havnt noticed this behaviour on FormLoad till now. But as I cant see any other problem in here its worth a try.
IF this doesnt solves it, you should also take care if TeacherScheduleForm is being called twice.
Something handy for debugging-purposes:
MessageBox.Show((new StackTrace().GetFrame(0).GetMethod().Name));
Paste this into your event/method or whatever. It will popup a messagebox with the method-name which called your current method. In this case (from comments) it would've raised 2 messageBoxes saying TeacherScheduleForm for both.
I've saved this to my code-snippets.
I have a class with an event and a custom EventArgs. The meaningful code:
public void OnTickReceived(TickReceivedEventArgs e)
{
EventHandler<TickReceivedEventArgs> handler = TickReceived;
if (handler != null)
handler(this, e);
}
public event EventHandler<TickReceivedEventArgs> TickReceived = delegate { };
and consuming the class in a UI Windows Form subscribing the event like this
private void button4_Click(object sender, EventArgs e)
{
bool esito;
t = new T3OpenStockReader();
esito = t.Connect();
textBox1.Text += "Connection: " + esito.ToString() + "\r\n";
Application.DoEvents();
if (esito)
{
esito = t.Subscribe("MI.EQCON.2552");
textBox1.Text += "Subscription: " + esito.ToString() + "\r\n";
Application.DoEvents();
}
if (esito)
{
t.Start();
t.TickReceived += NewTick_Event;
System.Diagnostics.Debug.Print("Reading started...");
}
}
private void NewTick_Event(object sender, TickReceivedEventArgs e)
{
textBox1.Text += e.tick.DT + " " + e.tick.Price + " " + e.tick.Volume + "\r\n";
}
I receive an InvalidOperationException - cross.thread operation. What am I doing wrong?
I receive InvalidOperationException - cross.thread operation. Where my error?
Presumably T3OpenStockReader raises events on its own thread - but you're trying to modify the UI in your event handler... which means you're doing it in the wrong thread. You should probably change your event handler to something like:
private void NewTick_Event(object sender, TickReceivedEventArgs e)
{
Action action = () => textBox1.Text += e.tick.DT + " " + e.tick.Price
+ " " + e.tick.Volume + "\r\n";
textBox1.BeginInvoke(action);
}
I'd also suggest that you get rid of your Application.DoEvents() calls - they're a symptom of trying to do too much in the UI thread.
I assume you are trying to update a UI component on a non-UI thread i.e. NewTick_Event. You need to force the update back onto the UI thread e.g.
private void NewTick_Event(object sender, TickReceivedEventArgs e)
{
textBox1.Invoke(new Action(() => textBox1.Text += e.tick.DT + " " + e.tick.Price + " " + e.tick.Volume + "\r\n"));
}
NewTick_Event is invoked from another thread and the changes on controls must be invoked on the UI thread (for example by using BeginInvoke method)
private void NewTick_Event(object sender, TickReceivedEventArgs e)
{
this.BeginInvoke( (Action) () =>
{
textBox1.Text += e.tick.DT + " " + e.tick.Price + " " + e.tick.Volume + "\r\n";
});
}
You get the violation because textBox1 is owned by a different thread. You have to invoke the functionality on the other thread. Invoking is like asking to the thread (thats owns the textBox1): "Here thread, execute this when you have time...". so the thread that owns the textBox1 will execute the functionality, instead of the thread that the event is raised from (or called, as events are call backs...).
I would go for this solution. Its a more generic approach than invoking on the textbox itself. And it doesn't matter what the event does, so you do not have to put all the functionality done by the event in a (Action) or BeginInvoke. You just simply call the event again, invoked, from the thread that owns the textbox.
Other answers in this topic do not check if invoke is required. I would say, that InvokeRequired boolean is there for a reason.
The FormParentOfTextBox in the example below is the instance of the form the textbox is put on. You could also use textBox1 here, but again, it would become less generic approach.
private void NewTick_Event(object sender, TickReceivedEventArgs e)
{
//Thread safe approach, generally for every event.
if (FormParentOfTextBox.InvokeRequired)
{
this.Invoke(NewTick_Event(sender, e));
return;
}
textBox1.Text += e.tick.DT + " " + e.tick.Price + " " + e.tick.Volume + "\r\n";
}
my class start new process (Tshark) and start capturing, from the main form i am checking the class properties in order to update my GUI, sometimes the received packets rate i so high that my GUI stuck so i want the option to check whose properties every 1-2 second.
this is my progress change function who checking my class all the time and in this point i am update my GUi, how can i checking those properties every 2 seconds ?
Tshark tshark = new Tshark();
private void bgWSniffer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
tshark = e.UserState as Tshark;
lblNumberOfReceivedPackets.Text = tshark._receivesPackets.ToString("#,##0");
lblTrafficRate.Text = (tshark._bitsPerSecond * 0.000001).ToString("0.##") + " Mbit/sec" + " (" + tshark._bitsPerSecond.ToString("#,##0") + " Bits/sec" + ")";
lblPacketsRate.Text = tshark._packetsPerSecond.ToString("#,##0") + " Packets/sec";
lblStatus.Text = tshark._status;
lblFileSize.Text = formatBytes(tshark._myFile.Length);
tshark._myFile.Refresh();
}
Check if 2 seconds has passed since the last check. Here, I'm using a class member to tract that time.
private DateTime _LastCheck = DateTime.MinValue;
private private void bgWSniffer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (_LastCheck.AddSeconds(2) <= DateTime.Now)
{
_LastCheck = DateTime.Now;
// do the UI update.
}
}
Instead of updating the UI within the BackgroundWorker you can just create a Timer to do the job
private void bgWSniffer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
tshark = e.UserState as Tshark;
}
In the ctor create the timer:
_timer = new Timer()
_timer.Intrerval = 2000;
_timer.Tick += UpdateUI;
_timer.Start();
You can add some checking in case the values have changed so you don't update the UI needlessly:
private void UpdateUI()
{
var local = _tshark;
if(local != null)
{
lblNumberOfReceivedPackets.Text = local._receivesPackets.ToString("#,##0");
lblTrafficRate.Text = (local._bitsPerSecond * 0.000001).ToString("0.##") + " Mbit/sec" + " (" + local._bitsPerSecond.ToString("#,##0") + " Bits/sec" + ")";
lblPacketsRate.Text = local._packetsPerSecond.ToString("#,##0") + " Packets/sec";
lblStatus.Text = local._status;
lblFileSize.Text = formatBytes(local._myFile.Length);
local._myFile.Refresh();
}
}
I'm trying to get this BackgroundWorker to work. When you click the View Orders button, it will display a message along the lines of "Retrieving new orders..." etc, and will do background work (mysql query), now, there's a bunch of stuff inside the DoWork method, and none of it gets done.
I know it's not because of the MySQL Query because it works fine on its own without the background worker.
Here's the code:
private void ViewOrders_Click(object sender, EventArgs e)
{
SlideTimer.Enabled = true;
Alert("Retrieving unconfirmed orders. Please wait.",
"Cancel",
Information,
true,
Color.FromArgb(63, 187, 249)
);
action = Action.ViewOrder;
bWorker.WorkerSupportsCancellation = true;
bWorker.DoWork += new DoWorkEventHandler(bWorker_DoWork);
bWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bWorker_RunWorkerCompleted);
bWorker.RunWorkerAsync();
}
void bWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
SlideTimer.Enabled = true;
Alert("All unconfirmed orders have been retrieved.",
"Dismiss",
Information,
true,
Color.FromArgb(63, 187, 249)
);
action = Action.None;
}
void bWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Connect to Database, check for orders, and end.
if (bWorker.CancellationPending == true)
{
e.Cancel = true;
}
else
{
if (action == Action.ViewOrder)
{
thelist.Clear();
thelist.Visible = true;
thelist.BringToFront();
MessageBox.Show("");
thelist.Columns.Add("Order #");
thelist.Columns.Add("Name");
thelist.Columns.Add("E-mail Address");
thelist.Columns.Add("Delivery Address");
thelist.Columns.Add("Company");
thelist.Columns.Add("Phone Number");
// Check for new orders.
MySql.Data.MySqlClient.MySqlConnection msc = new MySql.Data.MySqlClient.MySqlConnection(cs);
try
{
msc.Open();
// Check for orders now.
string st = "SELECT DISTINCT(sessionid), firstname, lastname, email, streetaddress, suburb, postcode, state, company, phone FROM mysql_9269_dbase.order";
MySql.Data.MySqlClient.MySqlCommand cd = new MySql.Data.MySqlClient.MySqlCommand(st, msc);
MySql.Data.MySqlClient.MySqlDataReader msdr = cd.ExecuteReader();
while (msdr.Read())
{
if (thelist.Items.Count == 0)
{
ListViewItem LItem = new ListViewItem(msdr[0].ToString());
ListViewItem.ListViewSubItemCollection SubItems = new ListViewItem.ListViewSubItemCollection(LItem);
SubItems.Add(msdr[1].ToString() + " " + msdr[2].ToString());
SubItems.Add(msdr[3].ToString());
SubItems.Add(msdr[4].ToString() + " " + msdr[5].ToString() + " " + msdr[6].ToString() + " " + msdr[7]);
SubItems.Add(msdr[8].ToString());
SubItems.Add(msdr[9].ToString());
thelist.Items.Add(LItem);
thelist.Update();
}
else
{
sound.Play();
//status.Text = "Records found; Retrieving now.";
var found = false;
foreach (var item in thelist.Items)
{
if (item.ToString().Contains(msdr[0].ToString()))
found = true;
}
if (thelist.Items.Count == 0 || !found)
{
ListViewItem LItem = new ListViewItem(msdr[0].ToString());
ListViewItem.ListViewSubItemCollection SubItems = new ListViewItem.ListViewSubItemCollection(LItem);
SubItems.Add(msdr[1].ToString() + " " + msdr[2].ToString());
SubItems.Add(msdr[3].ToString());
SubItems.Add(msdr[4].ToString() + " " + msdr[5].ToString() + " " + msdr[6].ToString() + " " + msdr[7]);
SubItems.Add(msdr[8].ToString());
SubItems.Add(msdr[9].ToString());
thelist.Items.Add(LItem);
thelist.Update();
}
}
}
}
catch (Exception en)
{
Alert(en.Message,
"Retry",
Error,
true,
Color.FromArgb(249, 87, 55)
);
}
msc.Close();
}
thelist.Visible = true;
thelist.BringToFront();
}
}
private void MessageLink_Click(object sender, EventArgs e)
{
switch (MessageLink.Text)
{
case "Cancel":
bWorker.CancelAsync();
SlideTimer.Enabled = true;
Alert("You have successfully cancelled the current operation.",
"Dismiss",
Information,
true,
Color.FromArgb(63, 187, 249)
);
action = Action.None;
break;
case "":
break;
default:
break;
}
}
There's no errors or anything. Just that Nothing happens. What's causing the Background(so called)Worker to not DoWork()?
*Sorry for the lengthy code snip.
You've hooked up the callbacks but not actually called RunWorkerAsync to start it going.
As an aside, you're also calling UI elements in the DoWork method which will fail. You need to use BeginInvoke to mashal the updates back to the UI thread or do the updates in the RunWorkerComplete method (which is run on the UI thread automatically).
MessageBox.Show("");
This will cause a big problem.
You can't call UI from a non UI thread. I'm surprised that it hasn't raised an exception. At best it's probably causing your thread to abort and not do anything.
The theList looks like a UI element as well. If you are adding to control then you need to pass the data via an event to the UI so you can update it there.
You also have:
Alert(en.Message,
"Retry",
Error,
true,
Color.FromArgb(249, 87, 55)
);
In your exception handler. Again this looks like you are trying to call UI elements.