Capture class (Emgu) issue in multiple background worker threads - c#

I have a simple Winforms app that allows users to select multiple videos (files) simultaneously and runs background workers threads to loop through each of the videos in the BW. Have pasted code below, I get a NullReferenceException as "Unable to create capture from ..." at this line
Capture _capture = new Capture(videoFileName)
in processVideo method.
N.B: The same code work fine if I select a single video. So some issue with the multiple instances of Capture class.
I would expect the ProcessVideo method to have new instance of Capture and open it separately. Any ideas on what I might be doing wrong?
private void openVideoToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "Video | *.AVI;*.MPEG;*.WMV;*.MP4;*.MOV;*.MPG;*.MPEG;*.MTS;*.FLV";
ofd.Multiselect = true;
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string[] videos = ofd.FileNames;
if (videos != null)
{
BackgroundWorker[] bw = new BackgroundWorker[videos.GetLength(0)];
int n = 0;
foreach (string video in videos)
{
bw[n] = new BackgroundWorker();
bw[n].DoWork += new DoWorkEventHandler(bw_DoWork);
bw[n++].RunWorkerAsync(video);
}
}
}
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
string filename = (string)e.Argument;
ProcessVideo(filename);
}
private void ProcessVideo(string videoFileName)
{
Capture _capture = new Capture(videoFileName);
UInt64 TOTAL_FRAMES = Convert.ToUInt64(_capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT));
for (UInt64 n = 0; n < TOTAL_FRAMES; n++)
{
using (Image<Bgr, Byte> img1 = _capture.QueryFrame())
{
//do something with the frame
}
}
}

I suggest you to update Sourcesafe service pack
it may help you
[I think you code is perfect there is
nothing wrong in it.
You got an error while creating object it clearly saw that
there may be chance that file format is not supported
or may be internal error problem.]
Let me know that after doing updation it works or not.
Regards Red

Related

How can I load multiple images using LoadAsync() in C#?

I'm trying to update the GUI, and I have an asynchronous function that uses LoadAsyc(), when I load just one image, it works but when I try to load more than one, the second one doesn't display.
This my code:
public UserFriendlyInterface()
{
InitializeComponent();
locationFileH5 = "";
serverStatus = false;
ipAddress = getLocalIPAddress();
port = 5000;
watcher = new FileSystemWatcher(#"flask_server\cnn\_prepImages_");
watcher.EnableRaisingEvents = true;
watcher.Changed += watcher_Changed;
}
private void watcher_Changed(object sender, FileSystemEventArgs e)
{
updateImages();
}
async Task updateImages()
{
pictureBoxNormalImg.WaitOnLoad = false;
pictureBoxNormalImg.LoadAsync(#"flask_server\cnn\_prepImages_\normal.jpg");
pictureBoxSegmentation.WaitOnLoad = false;
pictureBoxSegmentation.LoadAsync(#"flask_server\cnn\_prepImages_\segmentation.jpg");
}
What you are trying to achieve can be achieved more robustly by querying the Name property of the FileSystemEventArgs object, and updating only the corresponding PictureBox.
private static void Watcher_Changed(object sender, FileSystemEventArgs e)
{
PictureBox pictureBox;
switch (e.Name.ToLowerInvariant())
{
case "normal.jpg": pictureBox = pictureBoxNormalImg; break;
case "segmentation.jpg": pictureBox = pictureBoxSegmentation; break;
default: pictureBox = null; break;
}
if (pictureBox != null)
{
Image image = null;
try
{
using (var temp = new Bitmap(e.FullPath))
{
image = new Bitmap(temp);
}
}
catch { } // Swallow exception
if (image != null)
{
pictureBox.Invoke((MethodInvoker)(delegate ()
{
pictureBox.Image = image;
}));
}
}
}
I would avoid the LoadAsync method because it is intended mainly for loading images from the internet, and because I don't totally trust it.
Update: There were two problems with my initial code:
1) Free file locked by new Bitmap(filePath)
2) FileSystemWatcher Changed event is raised twice
The updated code solves these problems (hopefully), but not in the most robust or efficient way possible.
Update: To make the code more efficient, by avoiding the repeated loading of the images caused by multiple firings of the Changed event, you could use the extension method OnChanged found in this answer. It suffices to replace the line below:
watcher.Changed += Watcher_Changed;
...with this one:
watcher.OnChanged(Watcher_Changed, 100);

FileSystem Watcher- Checking if copied file is an Image

I'm monitoring a Folder for File creation(Copied) event using FileSystem Watcher. I only want the program to process image Files.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Filter = "*.*";
watcher.Created += new FileSystemEventHandler(watcher_FileCreated);
watcher.Path = path;
So I try to create a Bitmap and avoid the file if an exception is thrown
private static void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
try
{
using (Bitmap test = new Bitmap(Bitmap.FromFile(e.FullPath)))
{
mytoprocesslist.add(e.FullPath);
}
//do my processing with image
Console.WriteLine(e.FullPath);
}
catch (Exception error)
{
Console.WriteLine("File Error");
}
}
This throws Out of Memory exception even when a valid image file is copied, which I think happens because the event was raised before the file was copied completely. How can I get over this? I only want to add the valid image files to a to do list and I will process these images one by one later.
A bit cleaner solution than a Try-Catch might be this one.
Im using this code without any exceptions raised.
private static bool IsImage(string path) {
try {
var result = false;
using (var stream = new FileStream(path, FileMode.Open)) {
stream.Seek(0, SeekOrigin.Begin);
var jpg = new List<string> { "FF", "D8" };
var bmp = new List<string> { "42", "4D" };
var gif = new List<string> { "47", "49", "46" };
var png = new List<string> { "89", "50", "4E", "47", "0D", "0A", "1A", "0A" };
var imgTypes = new List<List<string>> { jpg, bmp, gif, png };
var bytesIterated = new List<string>();
for (var i = 0; i < 8; i++) {
var bit = stream.ReadByte().ToString("X2");
bytesIterated.Add(bit);
var isImage = imgTypes.Any(img => !img.Except(bytesIterated).Any());
if (isImage) {
result = true;
break;
}
}
}
return result;
} catch (UnauthorizedAccessException) {
return false;
}
}
Usage of code
foreach (var file in Directory.EnumerateFiles(#"pathToFlowersFolder"))
{
Console.WriteLine($"File: {file} Result:{IsImage(file)}");
}
Edit
After playing around i got an IO-Exception (File already in use)
After reading this i'd offer you the following solution:
private void button1_Click(object sender, EventArgs e)
{
var watcher = new FileSystemWatcher();
watcher.Created += new FileSystemEventHandler(fileSystemWatcher1_Changed);
watcher.Path = #"c:\temp";
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
watcher.EnableRaisingEvents = true;
}
private void fileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e)
{
Thread.Sleep(100); // <- give the Creator some time. Increase value for greate pause
if (IsImage(e.FullPath))
{
Console.WriteLine("success----------->" + e.FullPath);
}
}
Note
This piece of code properly works on my machine. My HDD is an SSD, so you might need to increase the thread-sleeping time. It properly works for all images (jpg, bmp, gif, png) up to a size of 7 Mb (im quite sure and greater).
If this code doesnt works for you, please post the exception rather than uploading your code.
For the first requirement: "I only want the program to process image files"
private static void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
{
string strFileExt = getFileExt(e.FullPath);
// filter file types
if (Regex.IsMatch(strFileExt, #"\.png|\.jpg", RegexOptions.IgnoreCase))
{
//here Process the image file
}
}
For the second requirement: "Out of Memory Exception"
Here what happens is, when the file is created (only file name and some attributes) the system is calling the created event. Then the file changed event is also called
So you have to do the processing in the changed event. Also to prevent duplicate calling you have to add a filter to your watcher.
The following is the complete code.
private void fileSystemWatcher1_Changed(object sender, System.IO.FileSystemEventArgs e)
{
FileInfo fileInfo = new FileInfo(e.FullPath);
string strFileExt = fileInfo.Extension;
// filter file types
if (Regex.IsMatch(strFileExt, #"\.png|\.jpg", RegexOptions.IgnoreCase))
{
//here Process the image file
try
{
using (Bitmap test = new Bitmap(Bitmap.FromFile(e.FullPath)))
{
//Do your code here.
}
}
catch (Exception error)
{
Console.WriteLine("File Error");
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
fileSystemWatcher1.Path = #"C:\Users\Christlin\Desktop\res";
//To Prevent duplicated calling of changed event
fileSystemWatcher1.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;
}

Increment ProgressBar within another class

it's my first question I'm asking here, so please be gentle with me ;)
So I've actually got two WinForms in my C# application I'm writing at the moment (I'm quite new to C#).
This window has a button, which saves photos from an usb device you selected before in a list box to another folder.
After clicking on this button my main thread is of course busy with copying, so I decided to create another WinForm which contains my ProgressBar.
Foreach completed copy, I want to increment my ProgressBar accordingly.
So I count the number of copies I have to do and give it the progressbar as maximum. But my problem at the moment is, that I really don't know how to increment the ProgressBar without getting a Thread Unsafe Exception.
Here's my ProgressWindow code:
public partial class ProgressWindow : Form
{
BackgroundWorker updateProgressBarThread = new BackgroundWorker();
private Boolean _isThreadRunning = false;
public Boolean IsThreadRunning
{
get { return _isThreadRunning; }
set { _isThreadRunning = value; }
}
private int _progressbarLength;
public int ProgressbarLength
{
get { return _progressbarLength; }
set { _progressbarLength = value; }
}
private int progress = 1;
public ProgressWindow()
{
Show();
InitializeComponent();
}
private void StartUpdateThread(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
// Reports progress to the ProgressChangedEvent function. (Thread Safe)
}
private void FinishProgressThread(object sender, RunWorkerCompletedEventArgs e)
{
if (!_isThreadRunning)
{
MessageBox.Show("Erfolgreich kopiert");
Close();
}
}
private void ProgressChangedEvent(object sender, ProgressChangedEventArgs e)
{
this.copyProgressbar.Value = e.ProgressPercentage;
this.progressStatus.Text = e.ProgressPercentage.ToString();
}
public void CallUpdateThread()
{
updateProgressBarThread.WorkerReportsProgress = true;
updateProgressBarThread.DoWork += new DoWorkEventHandler(StartUpdateThread);
updateProgressBarThread.ProgressChanged += new ProgressChangedEventHandler(ProgressChangedEvent);
updateProgressBarThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FinishProgressThread);
updateProgressBarThread.RunWorkerAsync();
}
}
I want to increment my ProgressBar with 1 after each succesful copy.
How do I do this from my main thread?
This is the function which actually handles the copy process
private void SaveFile(System.IO.DirectoryInfo root)
{
try
{
IEnumerable<DirectoryInfo> directoriesNames = root.EnumerateDirectories();
// New instance of thread ProgressWindow.
ProgressWindow progress = new ProgressWindow();
progress.CallUpdateThread();
foreach (DirectoryInfo element in directoriesNames)
{
// Query all subdirectories and count everything with the in the configuration made settings.
if (!element.Attributes.ToString().Contains("System"))
{
// Now we insert the configuration we applied.
String fileExtension = null;
if (Properties.Settings.Default._configPhoto)
{
fileExtension = "*.jpg";
}
if (Properties.Settings.Default._configWordDocument)
{
fileExtension = "*.odt";
}
FileInfo[] jpgList = element.GetFiles(fileExtension, SearchOption.AllDirectories);
// set the size of the progress bar
progress.ProgressbarLength = jpgList.Count();
// Now we go through all our results and save them to our backup folder.
foreach (FileInfo tmp in jpgList)
{
string sourceFilePath = tmp.FullName;
string destFilePath = PATHTOBACKUP + "\\" + tmp.Name;
progress.IsThreadRunning = true;
try
{
System.IO.File.Copy(sourceFilePath, destFilePath, true);
}
catch (IOException ioe)
{
MessageBox.Show(ioe.Message);
}
}
}
}
// progress.IsThreadRunning = false;
}
catch (UnauthorizedAccessException e)
{
MessageBox.Show(e.Message);
}
}
It's pretty obvious that I have to do this after this function
System.IO.File.Copy(sourceFilePath, destFilePath, true);
But how do I report this to my ProgressWindow?
I really hope I explained it well enough, not sure if I'm missing something important.
Thanks in advance guys
Here is a compact example of the key components:
Clicking button starts new thread worker
Progress is done by file lengths, not by number of files
BeginInvoke used to update the progress bar (avoid cross Thread exception)
ProgressBar pb = new ProgressBar() { Minimum = 0, Maximum = 100 };
Button btn = new Button();
btn.Click += delegate {
Thread t = new Thread(() => {
DirectoryInfo dir = new DirectoryInfo("C:\\temp\\");
var files = dir.GetFiles("*.txt");
long totalLength = files.Sum(f => f.Length);
long length = 0;
foreach (var f in files) {
length += f.Length;
int percent = (int) Math.Round(100.0 * length / totalLength);
pb.BeginInvoke((Action) delegate {
pb.Value = percent;
});
File.Copy(f.FullName, "...");
}
});
t.IsBackground = true;
t.Start();
};

How to delete the file after 30 seconds/ or delete the file once after the job is completed

I am working on a C# project and i need the file to deleted after 30 seconds. So once the file sent to the machine i need the software to count till 30 seconds and at same time show a splash form and once 30 seconds crossed close the splash screen and then delete the file.
I have added a splash screen called "image". So now what happens is, the data is only sent to the printer after the splash screen is closed. I need to multi thread the job. I mean the data should print in one side while the splash screen should show at the same time. Is there a way i can come out!!.. Please help me out.
So in my case i am copying the file to the bin/debug folder. then sending data to the machine simultaneously show the splash screen for 30 seconds and close the splash screen and then i need to delete the file..
codes:
private void button4_Click(object sender, EventArgs e)
{
//string filePath = image_print();
// MessageBox.Show(filePath, "path");
string s = image_print() + Print_image();
if (String.IsNullOrEmpty(s) || img_path.Text == "")
{
return;
}
else
{
//here its coming to the splash screen code, But data is transferred to the machine only after the splash screen is close :-(
this.Hide();
omg = new image();
omg.ShowDialog();
this.Show();
//splash screen closed and then data is transferred.. which i don't need.. i need simultaneous job to be done at the same time..
PrintFactory.sendTextToLPT1(s);
}
}
private string image_print()
{
OpenFileDialog ofd = new OpenFileDialog();
string path = "";
string full_path = "";
string filename_noext = "";
ofd.InitialDirectory = #"C:\ZTOOLS\FONTS";
ofd.Filter = "GRF files (*.grf)|*.grf";
ofd.FilterIndex = 2;
ofd.RestoreDirectory = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
filename_noext = System.IO.Path.GetFileName(ofd.FileName);
path = Path.GetFullPath(ofd.FileName);
img_path.Text = filename_noext;
//MessageBox.Show(filename_noext, "Filename"); - - -> switching.grf
// MessageBox.Show(full_path, "path");
//move file from location to debug
string replacepath = #"\\bin\Debug";
string fileName = System.IO.Path.GetFileName(path);
string newpath = System.IO.Path.Combine(replacepath, fileName);
// string newpath = string.Empty;
if (!System.IO.File.Exists(filename_noext))
System.IO.File.Copy(path, newpath);
filename_noext = img_path.Text;
MessageBox.Show(filename_noext, "path");
}
if (string.IsNullOrEmpty(img_path.Text))
return "";//
StreamReader test2 = new StreamReader(img_path.Text);
string s = test2.ReadToEnd();
return s;
}
private string Print_image()
{
//some codes
return s;
}
In image form: I have the following codes
public partial class image : Form
{
string filePath;
public image()
{
InitializeComponent();
// this.filePath = FileToDeletePath;
System.Timers.Timer timer1 = new System.Timers.Timer();
timer1.Interval = 30000;
timer1.Elapsed += timer1_Elapsed;
timer1.Start();
}
private void image_Load(object sender, EventArgs e)
{
}
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
//delete the file using "filePath"
string Filename = img_path.Text; // here i cannot pass the old string file name with extension to this form.. Any ways please help me out
if (string.IsNullOrEmpty(Filename))
return;
if (Filename.ToCharArray().Intersect(Path.GetInvalidFileNameChars()).Any())
return;
File.Delete(Path.Combine(#"\\bin\Debug", Filename));
}
}
something like this????
Task waitfordelete = Task.Run(() =>
{
image im = new image();
});
Assumptions: window image should be shown as a dialog (modal), and only while the call to PrintFactory.sendTextToLPT1 is in progress.
If that's correct, then something like this could work for you:
// Don't forget, you need to dispose modal dialogs
image omg = new image();
// Ensure the dialog has been shown before starting task. That
// way the task knows for sure the dialog's been opened and can
// be closed.
omg.Loaded += (sender, e) =>
{
// Run the print task in a separate task
Task.Run(() =>
{
PrintFactory.sendTextToLPT1(s);
// But get back onto the main GUI thread to close the dialog
Dispatcher.Invoke(() => omg.Close());
});
};
this.Hide();
omg.ShowDialog();
this.Show();
Apologies in advance for any typos/syntax errors/etc. Hopefully the above is sufficient to express the general idea.
The answer given by Narzul and Peter both are correct. You can implement any one. But, I know your next question will be how to implement that method in your code.
you can use Thread or Task class object to separate the process. So when one process is running then other process can perform their taks at that time. There are two process in your login. The first one is send the file to the printer and the second one is the show dialog for 30 seconds and then delete the file. You should create the another thread to invoke the any one of the process so other process can perform asynchronously.
1st: make the seperate process for Print file.
Task waitfordelete = Task.Run(() =>
{
PrintFactory.sendTextToLPT1(s);
});
this.Hide();
omg = new image();
omg.ShowDialog();
this.Show();
2nd: make the seperate process for show dialog and delete the file. But, I think you may get the error in this method. You cannot change the UI from other thread
Task waitfordelete = Task.Run(() =>
{
Dispatcher.Invoke(() => this.ShowSplashScreen());
});
PrintFactory.sendTextToLPT1(s);
private void ShowSplashScreen()
{
this.Hide();
omg = new image();
omg.ShowDialog();
this.Show();
}
if you don't want to use the thread or task then just simply handle the close event of Image form
this.Hide();
omg = new image();
omg.Show();
PrintFactory.sendTextToLPT1(s);
omg.FormClosed += (object sender, EventArgs e) => {
File.Delete(Path.Combine(Application.StartupPath, Path.GetFileName(img_path.Text));
this.Show();
};
and modify the code in timer_tick event in Image form and add the this.Close() after delete file statement.
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
....
//File.Delete(Path.Combine(#"\\bin\Debug", Filename)); comment this line
this.Close();
}
Another hidden question I have found here. here i cannot pass the old string file name with extension to this form.. Any ways please help me out
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
//delete the file using "filePath"
string Filename = img_path.Text; // here i cannot pass the old string file name with extension to this form.. Any ways please help me out
for that, you can create the property in Image class and assign the file name from the parent form.
Image omg = new Image()
omg.FileName = Path.Combine(Application.StartupPath, Path.GetFileName(img_path.Text));
omg.Show();
and the property in Image form will be created like this
public class Image : Form
{
public string FileName { get; set; }
public Image()
{
}
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
....
File.Delete(Path.Combine(Application.StartupPath, this.Filename));
this.Close();
}
}
NOTE: Use the Application.StartupPath istead of \\bin\debug

Add files to Listbox via Thread?

in my application i want to add files into my list box.
if my file isn't pcap extension i want to send the file path to my class and convet it to pcap extension and then add this file to my Listbox.
in case i am choose to add namy files the GUI not responding until my application finish to add or convert this file and i wonder how to add the option to do all this via threads.
private void btnAddfiles_Click(object sender, EventArgs e)
{
System.IO.Stream stream;
OpenFileDialog thisDialog = new OpenFileDialog();
thisDialog.InitialDirectory = (lastPath.Length > 0 ? lastPath : "c:\\");
thisDialog.Filter = "(*.snoop, *.pcap, *.cap, *.net, *.pcapng, *.5vw, *.bfr, *.erf, *.tr1)" +
"|*.snoop; *.pcap; *.cap; *.net; *.pcapng; *.5vw; *.bfr; *.erf; *.tr1|" + "All files (*.*)|*.*";
thisDialog.FilterIndex = 1;
thisDialog.RestoreDirectory = false;
thisDialog.Multiselect = true;
thisDialog.Title = "Please Select Source File";
if (thisDialog.ShowDialog() == DialogResult.OK)
{
if (thisDialog.FileNames.Length > 0)
{
lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
}
foreach (String file in thisDialog.FileNames)
{
try
{
if ((stream = thisDialog.OpenFile()) != null)
{
using (stream)
{
string fileToAdd = string.Empty;
Editcap editcap = new Editcap();
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork += new DoWorkEventHandler(
(s3, e3) =>
{
if (!editcap.isLibpcapFormat(file))
{
fileToAdd = editcap.getNewFileName(file);
}
else
{
listBoxFiles.Items.Add(file);
}
});
backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
(s3, e3) =>
{
listBoxFiles.Items.Add(fileToAdd);
});
backgroundWorker.RunWorkerAsync();
lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
}
}
Your application is freezing because you're doing a lot of work in the UI thread. You need to move the long running tasks to a background thread and then just update the UI in the UI thread.
The first thing that you need to do, in order to do that, is seperate out your long running task from your UI manipulation. Currently you're intermingliing the two, which is what's causing your confusion as to how to map it to a BackgroundWorker.
As long as you don't need to be updating the listbox iteratively and it's okay to just add all of the items at the end all at once (that's what I would expect out of a listbox) you can simply do your file IO in one place, adding the results into a collection of some sort (List is likely appropriate here) and then, separately, you can add all of the items in the list to your ListBox (or use data binding).
Once you make that change the move to using something like a BackgroundWorker is quite easy. The IO work that populates the List goes in the DoWork, runs in the background, and then sets the Result. The RunWorkerCompleted event then takes that lists and adds the items to the ListBox.
If you have a compelling need to add the items to the listbox as you go, so you see one item, then the next, etc. over time, then just think of it as "reporting progress" and use the relevant progress reporting functionality built into BackgroundWorker. Update the progress inside of the loop, and in the progress reported event handler take the value given to you and put it in the ListBox.
Here is an implementation:
private void btnAddfiles_Click(object sender, EventArgs e)
{
System.IO.Stream stream;
OpenFileDialog thisDialog = new OpenFileDialog();
thisDialog.InitialDirectory = (lastPath.Length > 0 ? lastPath : "c:\\");
thisDialog.Filter = "(*.snoop, *.pcap, *.cap, *.net, *.pcapng, *.5vw, *.bfr, *.erf, *.tr1)" +
"|*.snoop; *.pcap; *.cap; *.net; *.pcapng; *.5vw; *.bfr; *.erf; *.tr1|" + "All files (*.*)|*.*";
thisDialog.FilterIndex = 1;
thisDialog.RestoreDirectory = false;
thisDialog.Multiselect = true;
thisDialog.Title = "Please Select Source File";
if (thisDialog.ShowDialog() == DialogResult.OK)
{
if (thisDialog.FileNames.Length > 0)
{
lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
}
BackgroundWorker backgroundWorker = new BackgroundWorker();
backgroundWorker.WorkerReportsProgress = true;
backgroundWorker.DoWork +=
(s3, e3) =>
{
//TODO consider moving everything inside of the `DoWork` handler to another method
//it's a bit long for an anonymous method
foreach (String file in thisDialog.FileNames)
{
try
{
if ((stream = thisDialog.OpenFile()) != null)
{
using (stream)
{
Editcap editcap = new Editcap();
if (!editcap.isLibpcapFormat(file))
{
string fileToAdd = editcap.getNewFileName(file);
backgroundWorker.ReportProgress(0, fileToAdd);
}
else
{
backgroundWorker.ReportProgress(0, file);
}
lastPath = Path.GetDirectoryName(thisDialog.FileNames[0]);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
};
backgroundWorker.ProgressChanged +=
(s3, arguments) =>
{
listBoxFiles.Items.Add(arguments.UserState);
};
backgroundWorker.RunWorkerAsync();
}
}
You can do it with BackgroundWorker:
Add a backgroundWorker to your form via the Toolbox.
Start it with:
backgroundWorker.RunWorkerAsync(new string[] {parm1, parm2});
Add a events to backgroundWorker (Properties window)
Use DoWork to do your calculations. Then use RunWorkerCompleted to apply the settings.

Categories

Resources