The BackgroundWorker RunWorkerAsync method does not trigger DoWork(); - c#

I've been trying to get the BackGroundWorker to work for hours now. I can't seem to find out why my DoWork() eventhandler isn't getting raised after calling bgw.RunWorkerAsync();
I've cut down the irrelivant code, so it's a bit easyer to read.
namespace FolderMonitor
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using FolderMonitor.Properties;
public partial class MainForm : Form
{
private ExistingFileHandler exist = new ExistingFileHandler();
private MonitoredFileHandler handler = new MonitoredFileHandler();
private Monitor monitor;
private BackgroundWorker bgw = new BackgroundWorker();
public MainForm(Monitor monitor)
{
this.monitor = monitor;
InitializeComponent();
InitializeBackgroundWorker();
txtFolderPath.Text = Settings.Default.monitoredFolder;
txtNewFolderPath.Text = Settings.Default.destinationFolder;
btnStop.Enabled = false;
}
private void InitializeBackgroundWorker()
{
bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);
}
private void BtnStart_Click(object sender, EventArgs e)
{
btnStop.Enabled = true;
btnStart.Enabled = false;
exist.HandleExistingFiles(txtFolderPath.Text);
listBoxFiles.Items.Clear();
MonitoredFileHandler.MonitoredFolderPath = txtFolderPath.Text;
MonitoredFileHandler.DestinationFolderPath = txtNewFolderPath.Text;
this.bgw.RunWorkerAsync();
}
private void BtnStop_Click(object sender, EventArgs e)
{
this.bgw.CancelAsync();
btnStart.Enabled = true;
btnStop.Enabled = false;
}
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if (!worker.IsBusy)
{
monitor.StartFolderMonitor(txtFolderPath.Text);
}
}
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnStart.Enabled = true;
btnStop.Enabled = false;
}
private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
handler.MonitoredFiles.Add(txtNewFolderPath.Text);
}
}
}

BackgroundWorker.IsBusy will be true after its background thread been started, so it will always be true where you are testing it inside bgw_DoWork(). Therefore, monitor.StartFolderMonitor(txtFolderPath.Text) will never be called.
What are you trying to test for? I think you can just remove the if (!worker.IsBusy) check.

Aside the aforementioned IsBusy issue, the fact that StartFolderMonitor begins with start as opposed to DoFolderMonitoring or something similar, it is perhaps non-blocking therefore the DoWork handler exits immediately.

Just call
System.Windows.Forms.Application.DoEvents();
before bgw.RunWorkAsync();

Related

The process cannot access the file because it is being used by another process

The code that I got was from naudio record sound from microphone then save and many thanks to Corey
This is the error message that I get when I run the code for the second or subsequent times.
The first time it runs, it runs with no issues what so ever.
If I change the file name it works perfectly.
Unable to copy file "obj\Debug\Basque.exe" to "bin\Debug\Basque.exe". The process cannot access the file 'bin\Debug\Basque.exe' because it is being used by another process. Basque
Could someone gave me some guidance to where I'm making my error
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NAudio.Wave;
namespace Basque
{
public partial class FlashCard : Form
{
public WaveIn waveSource = null;
public WaveFileWriter waveFile = null;
public FlashCard()
{
InitializeComponent();
StopBtn.Enabled = false;
StartBtn.Enabled = true;
}
private void StartBtn_Click(object sender, EventArgs e)
{
StartBtn.Enabled = false;
StopBtn.Enabled = true;
waveSource = new WaveIn();
waveSource.WaveFormat = new WaveFormat(44100, 1);
waveSource.DataAvailable += new EventHandler<WaveInEventArgs>(waveSource_DataAvailable);
waveSource.RecordingStopped += new EventHandler<StoppedEventArgs>(waveSource_RecordingStopped);
waveFile = new WaveFileWriter(#"C:\Temp\bas0001.wav", waveSource.WaveFormat);
waveSource.StartRecording();
}
private void StopBtn_Click(object sender, EventArgs e)
{
StopBtn.Enabled = false;
waveSource.StopRecording();
}
void waveSource_DataAvailable(object sender, WaveInEventArgs e)
{
if (waveFile != null)
{
waveFile.Write(e.Buffer, 0, e.BytesRecorded);
waveFile.Flush();
}
}
void waveSource_RecordingStopped(object sender, StoppedEventArgs e)
{
if (waveSource != null)
{
waveSource.Dispose();
waveSource = null;
}
if (waveFile != null)
{
waveFile.Dispose();
waveFile = null;
}
StartBtn.Enabled = true;
}
private void PlayBtn_Click(object sender, EventArgs e)
{
}
private void ExitBtn_Click(object sender, EventArgs e)
{
}
}
}
It might help to put a Formclosing method with Application.Exit(); in it. If it only works on the first try, it might be because the application isn't fully closing.
You can check if this will fix it when you check task manager. Just make sure that your application isn't still there. Even if it isn't still there, the Application.Exit(); might help.

How can I get all my email messages using OpenPop and also show progress of messages retrieving on a progressBar?

This is a link for the OpenPop what I'm using in my project:
OpenPop
This is a page with examples:
Example
And this is my code. In form1 designer I added a progressBar.
What I want to do is to get all the messages I have on my server and show in a progressBar the progress of the messages retrieving.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Pop3_Emails
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
OpenPop.Pop3.Pop3Client PopClient = new OpenPop.Pop3.Pop3Client();
PopClient.Connect("mail.bezeqint.net", 110, false);
PopClient.Authenticate("meemail", "password",
OpenPop.Pop3.AuthenticationMethod.UsernameAndPassword);
int messageCount = PopClient.GetMessageCount();
List<Message> allMessages = new List<Message>(messageCount);
for (int i = messageCount; i > 0; i--)
{
allMessages.Add(PopClient.GetMessage(i));
}
backgroundWorker1.ReportProgress(0,PopClient.GetMessageCount().ToString());
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = e.UserState.ToString();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
}
}
The first problem is that i'm getting two errors on the line:
allMessages.Add(PopClient.GetMessage(i));
Error 1 The best overloaded method match for
'System.Collections.Generic.List.Add(System.Windows.Forms.Message)'
has some invalid arguments
Error 2 Argument 1: cannot convert from 'OpenPop.Mime.Message' to
'System.Windows.Forms.Message'
The second problem is how to report to the progressBar the progress ? Somehow from inside the FOR loop.
I think, first question is solved by AlexK.
Second question can by solved by setting:
backgroundWorker1.WorkerReportsProgress = true;
and in your for loop you can calculate and report progress by:
int nProgress = (messageCount - i) * 100 / messageCount;
backgroundWorker1.ReportProgress(0, nProgress);
So now, you can show your progress:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
int nProgress = (int)e.UserState;
label1.Text = nProgress.ToString();
progressBar1.Value = nProgress;
}
But what i also see is, that you are adding all downloaded messages to local variable List<Message> allMessages. So they get lost when downloading has finished. May be you should move it into the class...

Time stamp missing

I'm trying to display the data received on textbox. But I realized that when data were being received on Br#y terminal it look fine (eg. 14:02:33.43 > T 11 22.32) but running on the software the time stamp is missing.
Am I missing out anything which lead to this?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.OleDb;
using System.IO;
namespace SerialCom
{
public partial class Form1 : Form
{
string RxString; //Variable
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
serialPort1.PortName = "COM4";
serialPort1.BaudRate = 9600;
serialPort1.Open();
if (serialPort1.IsOpen)
{
btnStart.Enabled = false;
btnStop.Enabled = true;
txtData.ReadOnly = false;
}
}
private void btnStop_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.Close();
btnStart.Enabled = true;
btnStop.Enabled = false;
txtData.ReadOnly = true;
}
}
private void txtData_KeyPress(object sender, KeyPressEventArgs e)
{
if (!serialPort1.IsOpen) return; // If the port is closed, don't try to send a character.
char[] buff = new char[8]; // If the port is Open, declare a char[] array with one element.
buff[0] = e.KeyChar; // Load element 0 with the key character.
serialPort1.Write(buff, 0, 1); // Send the one character buffer.
e.Handled = true;// Set the KeyPress event as handled so the character won't
// display locally. If you want it to display, omit the next line.
}
private void DisplayText(object sender, EventArgs e)
{
txtData.AppendText(RxString);
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
RxString = serialPort1.ReadExisting();
this.Invoke(new EventHandler(DisplayText));
StreamWriter MyStreamWriter = new StreamWriter(#"c:\testing.txt",true); //True tell SW to append to file instead of overwriting
MyStreamWriter.Write(RxString);
MyStreamWriter.Flush();
MyStreamWriter.Close();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (serialPort1.IsOpen)
serialPort1.Close();
}
}
}
Basically, I was wrong by saying that the time stamp is originally included in the data i received.. I need to add in the time stamp on my own.. This was to act as a record of when did i actually received the following data.
As a result, what's missing is this
string time = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss.ff")
Hope this helps people who are struggling with the problem too.

Using AFORGE to record the videos in c#

i've try the following way to record the video from the Webcam by 25 Frame-rate per sec for 10sec but when i get the out put video it is of 2sec and the frames are played to fast as compare to the video stream.
The code is as follows.
using System;
using System.Drawing;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;
using System.Threading;
using AForge.Video.FFMPEG;
namespace AforgeTutorial
{
public partial class Form1 : Form
{
private FilterInfoCollection ListOfCams;
private VideoCaptureDevice SelectedCam; //From where we will take image
System.Timers.Timer tim;
Thread t;
bool isNewFrame = false;
VideoFileWriter writer;
public Form1()
{
InitializeComponent();
tim = new System.Timers.Timer(10000);
tim.Elapsed += new System.Timers.ElapsedEventHandler(tim_Elapsed);
t = new Thread(saveVideo);
}
void tim_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (isRecord)
{
writer.Close();
isRecord = false;
}
}
private void Form1_Load(object sender, EventArgs e)
{
ListOfCams = new FilterInfoCollection(FilterCategory.VideoInputDevice);
if (ListOfCams.Count == 0)
return;
comboBox1.Items.Clear();
foreach (FilterInfo Cam in ListOfCams)
{
comboBox1.Items.Add(Cam.Name);
}
}
private void StopCamera()
{
SelectedCam.SignalToStop();
SelectedCam.Stop();
}
bool isRecord = false;
private void Start_Click(object sender, EventArgs e)
{
if (comboBox1.Text == string.Empty)
return;
SelectedCam = new VideoCaptureDevice(ListOfCams[comboBox1.SelectedIndex].MonikerString);
SelectedCam.NewFrame += new NewFrameEventHandler(SelectedCam_NewFrame);
SelectedCam.Start();
}
Bitmap image;
void SelectedCam_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
image = (Bitmap)eventArgs.Frame.Clone();
isNewFrame = true;
pictureBox1.Image = (Bitmap)eventArgs.Frame.Clone();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
StopCamera();
}
private void Stop_Click(object sender, EventArgs e)
{
StopCamera();
}
private void btnRecord_Click(object sender, EventArgs e)
{
tim.Start();
if (!isRecord)
{
writer = new VideoFileWriter();
writer.Open(#"C:/code-bude_test_video.mp4", 640, 480, 25, VideoCodec.MPEG4,10000);
}
isRecord = !isRecord;
if (isRecord)
t.Start();
}
void saveVideo()
{
while (isRecord)
{
if (isNewFrame)
{
writer.WriteVideoFrame(image);
isNewFrame = false;
}
}
}
}
}
You have multi-threading issues in your code. You can't write to shared variables like that and expect it to synchronize.
You have three threads: user interface, streaming and saving. (SelectedCam_NewFrame runs in the AForge streaming thread). Make a list of all variables that are accessed in at least two threads (isRecord, isNewFrame, etc) and add proper synchronization.
You can check this very good reference on threading in C#.
Note that even with synchronization, you may miss frames if your writer thread is busy while several images arrive. What you might want to do is collect the frames produced by the camera in a queue and consume that queue in the writer thread. Check the producer/consumer patterns.

c# Forms Timer does not stop

I have a WinForms app that increments a timer once per second and updates a labels' text.
A second timer increments once every 20msec to look for recent mouse movements and writes the current coordinates to another label.
When the program receives Alt+F4 I instantiate "MessageBoxQueryClose" where the user is asked to close or resume operation. Before the MessageBox is displayed I'd like to stop
the once-per-second timer from firing, and after the user said "please continue" to re-enable it.
This is where I observed some 'strange' behavior: the once-per-second timer fires again
while the MessageBox is open and the mouse is moved.
Code for the form:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Globalization;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private bool _altF4Pressed = false;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Alt && e.KeyCode == Keys.F4)
_altF4Pressed = true;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// show the MessageBox asking the user if the programm should really exit
MessageBoxQueryClose msgBoxQC = new MessageBoxQueryClose();
msgBoxQC.QueryClose(ref _altF4Pressed, ref timer2, ref e);
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Interval = 20;
timer1.Enabled = true;
timer2.Interval = 1000;
timer2.Enabled = true;
}
bool toggle = false;
private void timer2_Tick(object sender, EventArgs e)
{
if (toggle)
label1.Text = "tick";
else
label1.Text = "tack";
toggle = !toggle;
}
Point oldPos, newPos;
private void timer1_Tick(object sender, EventArgs e)
{
newPos = Cursor.Position;
label2.Text = Convert.ToString(newPos.X + ", " + newPos.Y);
CompareCursorPosition();
oldPos = newPos;
}
private void CompareCursorPosition()
{
if (oldPos != newPos)
Display_ResetFallback();
}
private void Display_ResetFallback()
{
timer2.Stop();
timer2.Start();
}
}
}
Code for MessageBoxQueryClose:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
class MessageBoxQueryClose
{
public void QueryClose(ref bool _altF4Pressed, ref Timer timer, ref FormClosingEventArgs e)
{
if (_altF4Pressed)
{
// first, disable timer2 to stop Form1.label1 from being updated
timer.Enabled = false;
if (e.CloseReason == CloseReason.UserClosing)
{
DialogResult res;
res = MessageBox.Show("Close program ?", "timers",
MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
if (res == DialogResult.Yes)
{
return;
}
// if program execution shall continue, re-enable timer2
timer.Enabled = true;
}
e.Cancel = true;
_altF4Pressed = false;
}
}
}
}
I have the gut feeling that my issue is about timers and threading, but I only recently started out with .Net, so any insight is appreciated.
br, Chris
Your timer1_Tick event calls CompareCursorPosition(), which calls Display_ResetFallback(), which starts timer2 again.
So you stop timer2 in QueryClose(), but then the timer1_Tick event fires, starting timer2 up again.
You could modify Display_ResetFallback() to make sure your timer is only restarted if it's currently running:
if (timer2.Enabled)
{
timer2.Stop();
timer2.Start();
}
As a side note, I'd probably get rid of the MessageBoxQueryClose class entirely and just modify your FormClosing event accordingly:
if (e.CloseReason == CloseReason.UserClosing)
{
timer2.Stop();
if (MessageBox.Show("Close program ?", "timers", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
{
e.Cancel = true;
timer2.Start();
}
}
You can try this...
timer1.Stop();
label1.Text = timer1.Enabled == false ?"timer disabled":"timer enabled";
if (MessageBox.Show("Close program ?", "timers",
MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.OK)
{
//do stuff here if you want
}
timer1.Start();
label1.Text = timer1.Enabled == false ? "timer disabled" : "timer enabled";
just put those label text for you to check.
this edit you dont require the class
EDIT:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private bool _altF4Pressed = false;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Alt && e.KeyCode == Keys.F4)
_altF4Pressed = true;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//show the MessageBox asking the user if the programm should really exit
//MessageBoxQueryClose msgBoxQC = new MessageBoxQueryClose();
//msgBoxQC.QueryClose(ref _altF4Pressed, ref timer2, ref e);
if (_altF4Pressed)
{
this.timer2.Stop();
if (MessageBox.Show("Close program ?", "timers",
MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
{
e.Cancel = true;
this.timer2.Start();
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Interval = 20;
timer1.Enabled = true;
timer2.Interval = 1000;
timer2.Enabled = true;
}
bool toggle = false;
private void timer2_Tick(object sender, EventArgs e)
{
if (toggle)
label1.Text = "tick";
else
label1.Text = "tack";
toggle = !toggle;
}
//Point oldPos, newPos;
private void timer1_Tick(object sender, EventArgs e)
{
label2.Text = MousePosition.X.ToString() + " , " + MousePosition.Y.ToString();
}
//private void CompareCursorPosition()
//{
// if (oldPos != newPos)
// Display_ResetFallback();
//}
//private void Display_ResetFallback()
//{
// timer2.Stop();
// timer2.Start();
//}
}
Just put my first post inside your code....It stops for me,and no need for the extra class,removed the 2 points and the 2 methods(Display_ResetFallback and CompareCursorPosition),but you can use them(the 2 point variables) if you want and inside timer1 do your checks.

Categories

Resources