RunWorkerAsync returns busy state - c#

I'm using a BackgroundWorker to fetch data and update my UI. The code it's pretty self explanatory. When I click connect it connects to CANbus, starts background worker which fetches data and updates UI, when I click disconnect it stops fetching data from CANbus.
It works only for first time, when I'm trying to connect for the second time I'm getting an exception at RunWorkerAsync call which is inside RunWorkerCompleted callback about BackgroundWorker being busy and it cannot process more than one task at once.
That's what I don't quite understand, I'm making new instance of BackgroundWorker on every connection and have no idea why it's busy.
Looking for advice - thanks.
CANALHandle h;
BackgroundWorker canWorker;
private void bConnect_Click(object sender, RoutedEventArgs e)
{
if (this.h == 0) {
this.h = CANAL.CANALOpen("ED000200; 500", CANAL.FLAG_NONE);
canWorker = new BackgroundWorker();
canWorker.WorkerSupportsCancellation = true;
canWorker.WorkerReportsProgress = true;
canWorker.DoWork += (object s, DoWorkEventArgs ev) => {
if (CANAL.CANALDataAvailable(this.h) > 0) {
CANALMSG msg;
CANALStatus st = CANAL.CANALReceive(this.h, out msg);
ev.Result = msg;
}
};
canWorker.RunWorkerCompleted += (object s, RunWorkerCompletedEventArgs ev) => {
if (ev.Error != null) {
} else if (ev.Result != null) {
CANALMSG msg = (CANALMSG)ev.Result;
if (msg.id > 0) {
textCanId.Text = msg.id.ToString("X");
textCanLength.Text = msg.count.ToString("X");
textCanByte0.Text = (msg.count >= 1) ? msg.data[0].ToString("X2") : "";
textCanByte1.Text = (msg.count >= 2) ? msg.data[1].ToString("X2") : "";
textCanByte2.Text = (msg.count >= 3) ? msg.data[2].ToString("X2") : "";
textCanByte3.Text = (msg.count >= 4) ? msg.data[3].ToString("X2") : "";
textCanByte4.Text = (msg.count >= 5) ? msg.data[4].ToString("X2") : "";
textCanByte5.Text = (msg.count >= 6) ? msg.data[5].ToString("X2") : "";
textCanByte6.Text = (msg.count >= 7) ? msg.data[6].ToString("X2") : "";
textCanByte7.Text = (msg.count >= 8) ? msg.data[7].ToString("X2") : "";
}
}
canWorker.RunWorkerAsync();
};
canWorker.RunWorkerAsync();
}
}
private void bDisconnect_Click(object sender, RoutedEventArgs e)
{
if (this.h > 0) {
canWorker.CancelAsync();
canWorker.Dispose();
CANAL.CANALClose(this.h);
this.h = 0;
}
}

Related

WPF User Interface not updating without moving mouse

I am using background work to load some content but something really odd is happening the UI is not updating and it just begin to happen suddenly,
here follows the code
here is the button click
public void CarregaPaginaCTeTomador(object sender, RoutedEventArgs e)
{
if (ClassControleInstancia.CTeTomador == null)
{
ClassControleInstancia.CTeTomador = new Page_CTE_Tomador();
}
BackgroundWorker LoadPageWorker = new BackgroundWorker();
LoadPageWorker.DoWork += LoadPageWorker_DoWorkCteTomador;
LoadPageWorker.RunWorkerCompleted += LoadPageWorker_RunWorkerCompleted;
LoadPageWorker.RunWorkerAsync();
}
here is the 1° background work
private void LoadPageWorker_DoWorkCteTomador(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Antes do DoEvents");
System.Windows.Forms.Application.DoEvents();
Console.WriteLine("Apos o DoEvents");
ClassControleInstancia.JanelaPrincipal.Dispatcher.Invoke(() =>
{
_mainFrame.Navigate(ClassControleInstancia.CTeTomador);
ClassControleInstancia.CTeTomador.RefreshContent();
});
}
private void LoadPageWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
WaitNSeconds(80);
FrameCurrentPage();
}
Inside this ClassControleInstancia.CTeTomador.RefreshContent(); has another background work should this be the reason why the ui is getting stocked ?
Cause I am not seeing any problem with the code I am going mad cause I tried alread remove the bgwork but it still gets stocked.
the other bgwork is
private void CarregaGrid(int pagina, int quantidade, int TipoArquivo, int AscDesc, bool inognoreNot = false) //0 crescente 1 desc
{
//show the loader
ClassControleInstancia.JanelaPrincipal.Loader.Visibility = Visibility.Visible;
ClassControleInstancia.JanelaPrincipal.Loader_Abort.Visibility = Visibility.Hidden;
ClassControleInstancia.JanelaPrincipal.Loader_text.Visibility = Visibility.Hidden;
ClassControleInstancia.JanelaPrincipal.Loader_porgress.Visibility = Visibility.Hidden;
BackgroundWorker GridLoader = new BackgroundWorker();
GridLoader.DoWork += GridLoader_DoWork;
GridLoader.RunWorkerCompleted += GridLoader_RunWorkerCompleted;
GridLoader.RunWorkerAsync();
}
private void GridLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
dgUsers.Items.Refresh();
ClassControleInstancia.JanelaPrincipal.Loader.Visibility = Visibility.Hidden;
ButtonsSelector config = new ButtonsSelector();
config.OnViewStart(TipoArquivoOrdenacaoEnum.CTE_NaoTomador, botoesSelector(), "cte-nao-tomador");
}
private void GridLoader_DoWork(object sender, DoWorkEventArgs e)
{
Dispatcher.Invoke((() =>
{
ClassControleInstancia.JanelaPrincipal.Loader_percentage.Width = new GridLength(0);
}));
CurrentPage = GridParams.Pagina;
CurrentMaxRows = GridParams.QuantidadePorPagina;
ObjSenhaWebApi Senha = new ObjSenhaWebApi(Conexao.ARQBancoDeDados().BuscaSenhaWebApiUsuario());
ObjPesquisaNotas PesquisaNotas = new ObjPesquisaNotas();
PesquisaNotas.IdEmpresa = ClassControleInstancia.EmpresaSelecionada.EMP_SEQUENCIA_ORI;
PesquisaNotas.Pagina = GridParams.Pagina;
PesquisaNotas.QntdMostrar = GridParams.QuantidadePorPagina;
PesquisaNotas.Ordenacao = GridParams.TipoArquivo;
PesquisaNotas.CrescenteDecrescente = GridParams.IsAscDesc;
PesquisaNotas._ObjListaParametrosNfeSaida = new ObjListaParametrosNfeSaida();
PesquisaNotas._ObjListaParametrosNfeSaida.UsuarioId = Conexao.ARQBancoDeDados().BuscaSequenciaClienteOri();
PesquisaNotas.tipoTomador = 1;
#region CamposDaPesquisa
P_ADICIONA_CAMPOS_PESQUISA(PesquisaNotas);
#endregion
int V_EMPRESA = 0;
string V_NUMERO_NOTA = "";
Dispatcher.Invoke((Action)(() => V_NUMERO_NOTA = EDT_NUMERO_NOTA.Text.Trim()));
if (ClassControleInstancia.EmpresaSelecionada != null)
{
V_EMPRESA = ClassControleInstancia.EmpresaSelecionada.EMP_SEQUENCIA;
string V_FORNECEDOR = "";
Dispatcher.Invoke((Action)(() => V_FORNECEDOR = CbFornecedor.Text.ToString()));
Dispatcher.Invoke((Action)(() => dgUsers.ItemsSource = null));
List<Cte> ListaNotas = ArquivarNfeRest.ArquivarNfeRest.BuscaNotaSaida<Cte>(Senha, PesquisaNotas);
if (ListaNotas != null)
{
if (ListaNotas.Count() > 0)
{
Dispatcher.Invoke((Action)(() => nuvenzita_no_itens.Visibility = Visibility.Hidden));
}
else
{
Dispatcher.Invoke((Action)(() => nuvenzita_no_itens.Visibility = Visibility.Visible));
}
}
else
{
Dispatcher.Invoke((Action)(() => nuvenzita_no_itens.Visibility = Visibility.Visible));
}
//Colocar em negrito todos os matchs com a outra lista
List<string> ListaNegrito = ClassControleListaNegrito.BuscaLista(ClassControleInstancia.EmpresaSelecionada.EMP_SEQUENCIA, TipoArquivoOrdenacaoEnum.CTE_NaoTomador, true).ValorLista;
foreach (var item in ListaNotas)
{
foreach (var item2 in ListaNegrito)
{
if (item2 == item.CteSequencia.ToString())
{
item.NEGRITO = true;
}
}
}
ObjRetornoCount _ObjRetornoCount = ArquivarNfeRest.ArquivarNfeRest.BuscaQntdNotaSaida<Cte>(Senha, PesquisaNotas);
int QntdPaginas = _ObjRetornoCount.QntdPaginas;
int QntdNotas = _ObjRetornoCount.QntdTotal;
//Retira aviso vermelho (confima letura)
if (GridParams.IgnorarAlerta != true)
{
ClassDoReadNotification<Cte>.Verify();
ClassControleInstancia.Notifications.IsCteNaoTomadorRead = 1;
ClassControleInstancia.JanelaPrincipal.AlertaNovasNotas();
}
Dispatcher.Invoke((Action)(() =>
{
totalItensFiltrados = QntdNotas;
itensNoFiltro = ListaNotas;
if (VerificaSeTemFiltro() == 0)
{
paginatorTotal.Content = "Nº Total Doctos: " + (QntdNotas);
}
else
{
paginatorTotal.Content = "Nº Total Doctos Filtrados: " + (QntdNotas);
}
Pagenizer.getButtons(footer, QntdPaginas, CurrentPage, CurrentMaxRows, "cte-nao-tomador");
}));
//List<ObjSincronizados> ListaNotas = Conexao.ARQBancoDeDados().BuscaListaSincronizados(V_EMPRESA, V_NUMERO_NOTA, V_DATA_INICIAL, V_DATA_FINAL, V_FORNECEDOR);
Dispatcher.Invoke((Action)(() => dgUsers.ItemsSource = ListaNotas));
Dispatcher.Invoke((Action)(() =>
{
int tt = dgUsers.Items.OfType<Cte>().Where(x => x.MARCADO == true).Count();
int ttAll = dgUsers.Items.OfType<Cte>().Where(x => x.MARCADO == true || x.MARCADO == false).Count();
btCounter.Content = "Selecionados " + tt.ToString() + " de " + ttAll.ToString();
headerCheckBox.IsChecked = false;
}
));
}
}

Why i'm getting cross thread exception while updating label in backgroundworker progresschanged event?

I have a backgroundworker dowork where inside I start a new backgroundworker
DirectoryInfo MySubDirectory;
List<FileInfo> l;
object[] CurrentStatus;
private void _FileProcessingWorker_DoWork(object sender, DoWorkEventArgs e)
{
int countmore = 0;
try
{
DirectoryInfo[] MySubDirectories = (DirectoryInfo[])e.Argument;
for (int i = 0; i < MySubDirectories.GetLength(0); i++)
{
MySubDirectory = MySubDirectories[i];
l = new List<FileInfo>();
if (_FileCountingWorker.IsBusy == false)
_FileCountingWorker.RunWorkerAsync();
CurrentStatus = new object[6];
int totalFiles = l.Count;
CurrentStatus[3] = i.ToString();
countmore += totalFiles;
CurrentStatus[4] = countmore;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
string CurrentDirectory = "Current Directory: " + MySubDirectory.Name;
foreach (FileInfo MyFile in l)
{
CurrentStatus = new object[6];
if (_FileProcessingWorker.CancellationPending)
{
e.Cancel = true;
return;
}
if (MyFile.Extension.ToLower() == ".cs" || MyFile.Extension.ToLower() == ".vb")
{
string CurrentFile = "Current File: " + MyFile.Name;
string CurrentFileWithPath = MyFile.FullName;
CurrentStatus[0] = CurrentDirectory;
CurrentStatus[1] = CurrentFile;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
List<string> Result = SearchInFile(CurrentFileWithPath, "if");
if (Result != null && Result.Count > 0)
{
CurrentStatus[2] = Result;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
}
}
}
}
}
catch (Exception err)
{
return;
}
}
I'm checking the other backgroundworker is not busy if not start it
if (_FileCountingWorker.IsBusy == false)
_FileCountingWorker.RunWorkerAsync();
In the new backgroundworker dowork event
private void _FileCountingWorker_DoWork(object sender, DoWorkEventArgs e)
{
CountFiles(MySubDirectory, l);
}
In CountFiles
int countingFiles = 0;
private void CountFiles(DirectoryInfo di, List<FileInfo> l)
{
try
{
l.AddRange(di.EnumerateFiles());
}
catch
{
string fff = "";
}
try
{
if (di.FullName != BasePath)
{
IEnumerable<DirectoryInfo> subDirs = di.EnumerateDirectories();
if (subDirs.Count() > 0)
{
foreach (DirectoryInfo dir in subDirs)
{
CountFiles(dir, l);
countingFiles += 1;
if (countingFiles == 8382)
{
string hhhhh = "";
}
CurrentStatus[5] = countingFiles;
_FileCountingWorker.ReportProgress(0,CurrentStatus);
}
}
}
}
catch
{
string yyy = "";
}
}
Then in the second backgroundworker progresschanged
private void _FileCountingWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (typeof(object[]) == e.UserState.GetType())
{
object[] StatusMsg = (object[])e.UserState;
if (6 == StatusMsg.GetLength(0))
{
if (StatusMsg[5] != null)
{
lblCountingFiles.Text = StatusMsg[5].ToString();
}
}
}
}
The exception is on the line:
lblCountingFiles.Text = StatusMsg[5].ToString();
Cross-thread operation not valid: Control 'lblCountingFiles' accessed from a thread other than the thread it was created on
I'm updating the label in the ProgressChanged event. Why am I getting the exception?
And how should I solve it?
You are calling _FileCountingWorker.RunWorkerAsync(); in DoWork from another BackgroundWorker thread.
So when _FileCountingWorker reports progress it wont come back to the UI thread because it is not started from UI thread. That's why you are getting cross thread exception.
Try to call _FileCountingWorker.RunWorkerAsync() from UI thread or from _FileProcessingWorker_ProgressChanged event.
Otherwise you can use:
private void _FileCountingWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (!Dispatcher.CheckAccess()) // CheckAccess returns true if you're on the dispatcher thread
{
Dispatcher.Invoke(new Action<object, ProgressChangedEventArgs>(_FileCountingWorker_ProgressChanged), sender, e);
return;
}
if (typeof(object[]) == e.UserState.GetType())
{
object[] StatusMsg = (object[])e.UserState;
if (6 == StatusMsg.GetLength(0))
{
if (StatusMsg[5] != null)
{
lblCountingFiles.Text = StatusMsg[5].ToString();
}
}
}
}
I think the problem is on the main thread you have
object[] CurrentStatus;
in the background you could be newing it before reports progress gets to it
(or at the same time)
kill the above
just create the object in the do_work
object[] CurrentStatus = new object[6];

Thread Method Outrunning ProgressChanged

I have a simple application that executes a function in a separate thread via a BackgroundWorker and am running into issues. I am collecting a string array of values and passing that back to my ProgressChanged event via the ReportProgress method and I'm running into a problem where the thread continues and is so fast, it outruns the ProgressChanged event and overwrites the values before they can be added to a grid. Below is my code...
Button Click Event Fires my thread...
private void LoadButton_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(WorkingPathTextBox.Text))
{
this.dataGridView1.Rows.Clear();
this.progressBar1.Visible = true;
this.LoadButton.Visible = false;
this.BrowseButton.Enabled = false;
this.WorkingPathTextBox.Enabled = false;
this.CancelBtn.Visible = true;
this.ProcessingLabel.Visible = true;
beginTime = DateTime.Now;
WorkflowCleanup wc = new WorkflowCleanup();
wc.WorkflowPath = this.WorkingPathTextBox.Text;
backgroundWorker1.RunWorkerAsync(wc);
}
}
In the DoWork, it loads the class where my work exists...
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
System.ComponentModel.BackgroundWorker worker;
worker = (System.ComponentModel.BackgroundWorker)sender;
// Get the Words object and call the main method.
WorkflowCleanup wc = (WorkflowCleanup)e.Argument;
wc.LoadAssemblies(worker, e);
wc.LoadDataDefinitions(worker, e);
wc.LoadDataDefinitionsDirty(worker, e);
wc.LoadProcesses(worker, e);
wc.LoadProcessesDirty(worker, e);
wc.LoadWorkflows(worker, e);
// wc.UpdateWorkflows(worker, e);
}
WorkflowCleanup class...the ReportProgress in stuck right in the middle of the try/catch because I could not figure out what was causing the problem. So, I moved it in the try, and even had to add a Thread.Sleep(100) to slow the process down to give the ProgressChanged event time enough to add the row of data I passed it to the grid before it was overridden...
namespace WorkflowMaintenance
{
public class WorkflowCleanup
{
private int errorCount = 0;
private int fixCount = 0;
public class Workflow
{
// code truncated
}
public class WorkflowAssembly
{
// code truncated
}
public class DataDefinition
{
// code truncated
}
public class CurrentState
{
public int Percentage;
public string StateString;
public List<string[]> ProcessResults;
public string[] Result;
public int ErrorCount;
public int FixCount;
}
public void LoadAssemblies(System.ComponentModel.BackgroundWorker worker, System.ComponentModel.DoWorkEventArgs e)
{
CurrentState state = new CurrentState();
fixCount = 0;
errorCount = 0;
string[] asmbfiles = System.IO.Directory.GetFiles(WorkflowPath + "\\Assemblies", "*.asmb", System.IO.SearchOption.AllDirectories);
int asmbIndex = 0;
Assemblies = new List<WorkflowAssembly>();
// Assemblies (NEW)
foreach (string asmb in asmbfiles)
{
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
else
{
//results = new List<string[]>();
asmbIndex += 1;
int percentage = (asmbIndex * 100) / asmbfiles.Length;
state.StateString = string.Format("Loading Assemblies... {0}%", percentage);
state.Percentage = percentage;
try
{
XDocument xdoc = XDocument.Load(asmb);
XElement asmbElement = xdoc.Descendants(wf + "assembly").First();
XElement asmbTypes = asmbElement.Element(wf + "types");
string asmbid = asmbElement.Attribute("id").Value;
string asmbname = asmbElement.Element(wf + "name").Value;
string asmbpath = asmbElement.Element(wf + "assemblyPath").Value;
Assemblies.Add(new WorkflowAssembly() { ID = asmbid, Name = asmbname, FileName = asmb, AssemblyPath = asmbpath, Types = asmbTypes });
//results.Add(new string[] { "SUCCESS", "ASSEMBLY PROCESSED SUCCESSFULLY", asmbname, asmbid, null, asmb });
state.Result = new string[] { "SUCCESS", "ASSEMBLY PROCESSED SUCCESSFULLY", asmbname, asmbid, null, asmb };
fixCount += 1;
//if (results != null && results.Count > 0)
//{
// state.ProcessResult = results;
//}
state.FixCount = fixCount;
state.ErrorCount = errorCount;
worker.ReportProgress(percentage, state);
Thread.Sleep(100);
}
catch (Exception)
{
// need to report the exception...
errorCount += 1;
}
finally
{
//if (results != null && results.Count > 0)
//{
// state.ProcessResult = results;
//}
//state.FixCount = fixCount;
//state.ErrorCount = errorCount;
//worker.ReportProgress(percentage, state);
}
}
}
}
}
}
ProgressChanged Event...
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// This method runs on the main thread.
WorkflowCleanup.CurrentState state = (WorkflowCleanup.CurrentState)e.UserState;
this.progressBar1.Value = state.Percentage;
this.ProcessingLabel.Text = state.StateString;
this.errorLabel.Text = string.Format("Errors: {0}", state.ErrorCount);
this.fixLabel.Text = string.Format("Fixed: {0}", state.FixCount);
this.ElapsedTimeLabel.Text = string.Format("Elapsed Time: {0}", GetProgressElapsedString());
if (state.Result != null)
{
this.dataGridView1.Rows.Add(state.Result);
}
}
Problem...the problem is that if I have 3 files in the folder (named Assembly1, Assembly2, and Assembly3), the output in the grid shows that all three are named Assembly3. The only way I could fix this was to tell the Thread to sleep. This is not an option as I have to run this for a folder that has approximately 18,000 files and having to sleep for a millisecond would take forever. BUT, I need to get valid results. Help please :-)
Rather than creating the state object outside the loop and mutating it in each iteration, create a new instance for each iteration. This can be done by simply moving the declaration of the variable inside the loop.

Can't get backgoundworker to work

I can't get background worker to work. This is my first time using it so I don't know if I have done something wrong. Here's my code:
int cardcount = 0;
string lev = "";
string att = "";
string atk = "";
string def = "";
string ctp = "";
string id = "";
void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if (folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string folder = folderBrowserDialog1.SelectedPath;
DirectoryInfo dinfo = new DirectoryInfo(folderBrowserDialog1.SelectedPath);
FileInfo[] Files = dinfo.GetFiles("*.jpg");
int count = Files.Length;
int current = 0;
foreach (FileInfo file in Files)
{
string path = Path.GetFileNameWithoutExtension(file.Name);
int cardid = Convert.ToInt32(path);
if (Program.CardData.ContainsKey(cardid))
{
DevPro_CardManager.cardmaker.IMG = LoadBitmap(folderBrowserDialog1.SelectedPath + "//" + file.Name);
id = Program.CardData[cardid].Id.ToString();
lev = Program.CardData[cardid].Level.ToString();
att = Program.CardData[cardid].Attribute.ToString();
if (att == "1")
{
att = "earth";
}
else if (att == "2")
{
att = "water";
}
else if (att == "4")
{
att = "fire";
}
else if (att == "8")
{
att = "wind";
}
else if (att == "16")
{
att = "light";
}
else if (att == "32")
{
att = "dark";
}
else if (att == "64")
{
att = "divine";
}
if (Program.CardData[cardid].Atk.ToString() == "-2")
{
atk = "????";
}
else
{
atk = Program.CardData[cardid].Atk.ToString();
}
if (Program.CardData[cardid].Def.ToString() == "-2")
{
def = "????";
}
else
{
def = Program.CardData[cardid].Def.ToString();
}
ctp = Program.CardData[cardid].Type.ToString();
if (ctp == "2" || ctp == "130" || ctp == "65538" || ctp == "131074" || ctp == "262146" || ctp == "524290")
{
ctp = "spell";
}
else if (ctp == "4" || ctp == "1048580" || ctp == "131076")
{
ctp = "trap";
}
else if (ctp == "129" || ctp == "161")
{
ctp = "ritual";
}
else if (ctp == "65" || ctp == "97")
{
ctp = "fusion";
}
else if (ctp == "8193" || ctp == "8225" || ctp == "12321")
{
ctp = "synchro";
}
else if (ctp == "8388609" || ctp == "8388641")
{
ctp = "xyz";
}
else if (ctp == "33" || ctp == "545" || ctp == "1057" || ctp == "2081" || ctp == "4129" || ctp == "4194337")
{
ctp = "effect";
}
else if (ctp == "17" || ctp == "4113")
{
ctp = "normal";
}
else if (ctp == "16401")
{
ctp = "token";
}
cardcount = cardcount + 1;
backgroundWorker1.ReportProgress((current * 100) / count);
}
}
}
}
void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// The progress percentage is a property of e
progressBar1.Value = e.ProgressPercentage;
label8.Text = cardcount.ToString();
comboBox2.SelectedItem = lev;
comboBox1.SelectedItem = att;
textBox2.Text = atk;
textBox1.Text = def;
comboBox3.SelectedItem = ctp;
GenerateCard();
ImageResizer.CropImage(361, 523, pictureBox1.Image, #"anime cards\" + Path.GetFileName(id));
}
And the code for the button that launches it:
private void button5_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
Please help or say if I'm doing something wrong, thanks.
If you really need to call ShowDialog from the background thread you will need to marshal the call to the foreground thread using Invoke. Here's an example of how you might do this:
public partial class Form1 : Form
{
private delegate DialogResult ShowFolderBrowser();
public Form1()
{
InitializeComponent();
}
private DialogResult ShowFolderBrowserDialog()
{
return this.folderBrowserDialog1.ShowDialog();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
if ((DialogResult)this.Invoke(this.ShowFolderBrowserDialog) == DialogResult.OK)
{
// ...
}
}
private void button1_Click(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync();
}
}
However, I would recommend that you rethink your design somewhat. You never explained why you're using a BackgroundWorker in the first place. Why can't you start up the BackgroundWorker after you've shown the folder browser dialog? Like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string folder = e.Argument as string;
// ...
}
private void button1_Click(object sender, EventArgs e)
{
if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
string folder = this.folderBrowserDialog1.SelectedPath;
this.backgroundWorker1.RunWorkerAsync(folder);
}
}
}
The most important detail you overlooked is that you have to do something reasonable when the worker threw an exception. At a minimum, you'll have to report it in your RunWorkerCompleted event handler:
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if (e.Error != null) {
MessageBox.Show(e.Error.ToString());
}
else {
// etc..
}
}
You will now also discover the problem in your code, you cannot use OpenFileDialog on a worker thread. Display it on the UI thread instead and then start the worker, passing the selection.
And yes, this is different from what you are used to, you expect the debugger to tell you about unhandled exceptions. That doesn't work the same way when a try/catch is wrapping code, they are built into the BackgroundWorker class. You can get the debugger to stop at such an invisible exception with Debug + Exceptions, tick the Thrown checkbox for CLR exceptions. This is not otherwise a good reason to skip the e.Error check in the event handler.

How to Fire an event for another Control while performing DataGridView_CellContentClick?

Actually, I have fired an event on DataGridView_CellContentClick which perform an operation relating to datagridview like changing cell's value But before performing this action i want to make changes(or fire) an another operation on another control i.e. ListView .But this is not gone happens although i place another operation before datagridview's operation. Anybody please help me out.
And my code goes like this:-
private void dGridDeviceList_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
//DataGridViewCell dcell = dGridDeviceList.Rows[e.RowIndex].Cells[e.ColumnIndex];
if (e.RowIndex >= 0)
{
ListViewItem litem1 = lvInformation.Items.Add("101");
litem1.SubItems.Add(string.Empty);
litem1.SubItems[1].Text = "Connected.";
ListViewItem litem5= lvErrorList.Items.Add("check ");
Cursor = Cursors.WaitCursor;
List<cException> cxp = new List<cException>();
cDeviceModel cdm = new cDeviceModel();
ListViewItem litem = new ListViewItem();
DataGridViewRow drow = new DataGridViewRow();
cDeviceUtility cUtil = new cDeviceUtility();
List<cAction> catn = new List<cAction>();
drow = dGridDeviceList.Rows[e.RowIndex];
cdm = (cDeviceModel)drow.Tag;
if (e.ColumnIndex == 6)
{
if (dGridDeviceList.CurrentCell.Value.ToString() == "Connect")
{
litem1= lvInformation.Items.Add("101");
litem1.SubItems.Add(string.Empty);
litem1.SubItems[1].Text = "Connected.";
//lvInformation.Items.Insert(0, "101");
//lvInformation.Items[0].SubItems.Add("Connected");
}
// connect disconnect button column
if (cdm.IsConnected)
{
ListViewItem litem2 = lvInformation.Items.Add("102");
litem2.SubItems.Add(string.Empty);
litem2.SubItems[1].Text =string.Format("Disconnecting from {0} device.",dGridDeviceList.CurrentRow.Cells["colDeviceName"].Value);
// then disconnect the device
cdm.IsConnected = false;
cdm.DeviceInterface.Disconnect();
dGridDeviceList.Rows[e.RowIndex].Tag = cdm;
dGridDeviceList.Rows[e.RowIndex].Cells[6].Value = "Connect";
dGridDeviceList.Rows[e.RowIndex].Cells[1].Value = img16x16.Images["notconnected"];
dGridDeviceList.Rows[e.RowIndex].Cells[8].Value= 0;
dGridDeviceList.Rows[e.RowIndex].Cells[8].Tag = "Not Connected";
dGridDeviceList.Refresh();
litem2 = lvInformation.Items.Add("103");
litem2.SubItems.Add(string.Empty);
litem2.SubItems[1].Text = string.Format("Disconnected from {0} device.", dGridDeviceList.CurrentRow.Cells["colDeviceName"].Value);
}
else
{
// string test = lvInformation.Items[0].SubItems[1].ToString();
// catn.Add(new cAction { Number = lvInformation.Items.Count+1, Message = string.Format("Trying to connect with {0}", dGridDeviceList.Rows[e.RowIndex].Cells["colDeviceName"].Value) });
//// lvInformation.Items.Clear();
// foreach (cAction Actn in catn)
// {
// litem=lvInformation.Items.Insert(0, (lvInformation.Items.Count + 1).ToString());
// litem.SubItems.Add(catn[catn.Count -1].Message);
// }
// then connect the device
if (!ConnectToDevice(ref drow, out cxp) == true)
{
foreach (cException err in cxp)
{
litem = lvErrorList.Items.Insert(0, err.Number.ToString());
if (err.EType == ErrorType.Error)
{
litem.ImageKey = "error";
}
else if (err.EType == ErrorType.Warning)
{
litem.ImageKey = "warning";
}
else if (err.EType == ErrorType.Information)
{
litem.ImageKey = "information";
}
litem.SubItems.Add(err.Message);
litem.SubItems.Add(err.Source);
}
}
else
{
dGridDeviceList.Rows[e.RowIndex].Cells[0].Value = true;
dGridDeviceList.Rows[e.RowIndex].Tag = drow.Tag;
dGridDeviceList.Rows[e.RowIndex].Cells[6].Value = "Disconnect";
dGridDeviceList.Rows[e.RowIndex].Cells[1].Value = img16x16.Images["connected"];
dGridDeviceList.Rows[e.RowIndex].Cells[8].Value = 0;
dGridDeviceList.Rows[e.RowIndex].Cells[8].Tag = "Ready";
dGridDeviceList.Refresh();
RemoveSelectionRow();
}
}
}
else if (e.ColumnIndex == 7)
{
// view logs button column
pbarMain.Value = 100;
ViewLogs(dGridDeviceList.Rows[e.RowIndex],ref lvAttnLog ,ref lvErrorList);
}
Cursor = Cursors.Arrow;
}
}
considering this is winform
private void buttonCopyContent_Click(object sender, EventArgs e)
{
//do something
}
you can call this event via following line
this.Invoke(new EventHandler(buttonCopyContent_Click));

Categories