I'm new to c# and currently working on a program. it has a simple UI, there are two buttons (one is called on and other one is off) and also a textbox to show some result. basically what I want to do is that if the user click "on" button, on a different class than the windows form random numbers will be generated every one second using a method. and by Implementing INotifyPropertyChanged I want to let the Textbox know that the value was updated so textbox keeps getting updated with our new random number. and once user click "off" button I want to stop generating random number.
My windows Form
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 SWE_Assignment
{
public partial class Monitor : Form
{
Patient newPatient = Patient.Instance;
public static bool pulseRateOn = false;
public Monitor()
{
InitializeComponent();
newPatient.PropertyChanged += _PulseRate_PropertyChanged;
}
private void Save_Click(object sender, EventArgs e)
{
// newPatient.PL(newPatient.startRnd = true;);
}
void _PulseRate_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "PulseRate")
{
HeartBeat.Text = newPatient.PulseRate.ToString();
}
}
private void Stop_Click(object sender, EventArgs e)
{
newPatient.startRnd = false;
}
}
}
My Patient Class
namespace SWE_Assignment
{
class Patient : INotifyPropertyChanged
{
private int _pulseRate;
public bool startRnd = false;
Random rnd = new Random();
public int PulseRate
{
get { return _pulseRate; }
set
{
_pulseRate = value;
OnPropertyChanged("PL");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string properyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(properyName));
}
private static Patient _instance = null;
private static readonly object _padlock = new object();
public static Patient Instance
{
get
{
lock (_padlock)
{
if (_instance == null)
{
_instance = new Patient();
}
return _instance;
}
}
}
public void PL(bool srt)
{
Timer timer = new Timer();
timer.AutoReset = true;
timer.Interval = 1000;
if (startRnd == true)
{
timer.Elapsed += PLS;
timer.Enabled = true;
timer.Start();
} else
{
timer.Enabled = false;
timer.Stop();
}
}
private void PLS(object sender, ElapsedEventArgs e)
{
PulseRate = rnd.Next(100, 150);
Console.WriteLine(PulseRate);
}
}
}
Also my I am using singleton pattern for my patient because I want to only have on instance of patient so that I can have access to the same random number on another class (called Alarm) to check if its bigger or smaller than a certain numbers. I do realise that is wrong with my "Stop" button as it only calls the method again and it doesn't stop method from running. I appreciate if anyone can help.
there are a few things which need to be changed.
OnPropertyChanged("PL"); - the name of property is PulseRate. "PulseRate" is what you check in event handler. make it OnPropertyChanged("PulseRate");
Timer timer = new Timer(); - you should create only one instance of Timer per Patient. better do it in constructor. otherwise you will have multiple running copies of Timer
managing Timer can be done via Enabled property:
Calling the Start() method is the same as setting Enabled to true. Likewise, calling the Stop() method is the same as setting Enabled to false.
private void Stop_Click(object sender, EventArgs e)
{
// newPatient.startRnd = false;
newPatient.PL(false);
}
class Patient : INotifyPropertyChanged
{
Timer timer;
private Patient()
{
timer = new Timer();
timer.AutoReset = true;
timer.Interval = 1000;
timer.Elapsed += PLS;
}
Random rnd = new Random();
private int _pulseRate;
public int PulseRate
{
get { return _pulseRate; }
set
{
_pulseRate = value;
OnPropertyChanged("PulseRate");
}
}
public void PL(bool srt)
{
timer.Enabled = srt;
}
private void PLS(object sender, ElapsedEventArgs e)
{
PulseRate = rnd.Next(100, 150);
Console.WriteLine(PulseRate);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string properyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(properyName));
}
private static Patient _instance = null;
private static readonly object _padlock = new object();
public static Patient Instance
{
get
{
lock (_padlock)
{
if (_instance == null)
{
_instance = new Patient();
}
return _instance;
}
}
}
}
Related
I open multiple serial ports and assign the DataReceived event to a single method. If now multiple com ports receive at the same time something, SerialPort_DataReceived is called parallel(?) so i tried to use lock so that only one event could be handled at the same time.
using System;
using System.Collections.Generic;
using System.Windows;
using System.IO.Ports;
using System.Text;
namespace MainApplication
{
public partial class MainWindow : Window
{
private SerialConnectionHandler m_SerialConnectionHandler;
public MainWindow()
{
InitializeComponent();
m_SerialConnectionHandler = new SerialConnectionHandler();
m_SerialConnectionHandler.ResponseReceived += SerialConnectionHandler_ResponseReceived;
}
private void SerialConnectionHandler_ResponseReceived(object sender, EventArgs e)
{
// Do something.
}
}
public class SerialConnectionHandler
{
private List<SerialPort> m_SerialConnections;
private List<SerialCommand> m_CommandQueue;
private object m_DataReceivedLock;
public event EventHandler ResponseReceived;
public SerialConnectionHandler()
{
m_SerialConnections = new List<SerialPort>();
m_CommandQueue = new List<SerialCommand>();
m_DataReceivedLock = new object();
foreach (var comPortName in SerialPort.GetPortNames())
{
var newSerialPort = new SerialPort(comPortName);
newSerialPort.DataReceived += SerialPort_DataReceived;
var newSerialCommand = new SerialCommand(comPortName, "Command", "Response");
newSerialPort.Open();
newSerialPort.Write(newSerialCommand.Command, 0, newSerialCommand.Command.Length);
m_SerialConnections.Add(newSerialPort);
}
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
lock (m_DataReceivedLock)
{
var serialPort = (SerialPort)sender;
var receivedContent = new byte[serialPort.BytesToRead];
serialPort.Read(receivedContent, 0, receivedContent.Length);
// Clear in buffer.
serialPort.DiscardInBuffer();
// Do something which could lead to problems if multiple com ports receive at the same time something.
foreach (var command in m_CommandQueue.FindAll(command => command.SerialPortName.Equals(serialPort.PortName)))
{
if (command.ExpectedResponse.Equals(receivedContent.ToString()))
{
ResponseReceived?.Invoke(this, new EventArgs());
m_CommandQueue.Remove(command);
break;
}
}
}
}
}
public class SerialCommand
{
public string SerialPortName { get; }
public byte[] Command { get; }
public string ExpectedResponse { get; }
public SerialCommand(string serialPortName, string command, string expectedResponse)
{
SerialPortName = serialPortName;
Command = Encoding.ASCII.GetBytes(command);
ExpectedResponse = expectedResponse;
}
}
}
My question is now, could lock lead to missed received content due to the fact that not every event is handled immediately? I'm calling SerialPort.Read() and SerialPort.DiscardInBuffer() from inside the lock block.
I'm having trouble figuring out what is wrong with my C# code.
I'm trying to learn how to use ConcurrentQueue class in System.Collections.Concurrent namespace.
In order to do this, I'm creating 2 instances of the same class in different threads, passing to the constructors a different Listbox control.
I am expecting each class instance of EventGenerator to raise events at random intervals, updating the Listbox the were passed with randomly generated number, and adding that number to a ConcurrentQueue which is also passed to the constructor.
In my main thread, is the method to DeQueue the ConcurrentQueue of objects EnQueued to it by both spawned threads.
But what I'm getting is the 2 EnQueue Listboxes displaying the same data and the DeQueue Listbox seeming reporting to have deQueued them both.
I apologize if my description is not good enough, and my code follows, along with a link to an image of my form in case it might better help visualize what I'm trying to do...
Form
public partial class Form1 : Form
{
ConcurrentQueue<int> CQ;
EventGenerator eventGenerator1;
EventGenerator eventGenerator2;
public Form1()
{
InitializeComponent();
CQ = new ConcurrentQueue<int>();
eventGenerator1 = new EventGenerator(CQ, listBox1);
eventGenerator1.OnRandomEvent += new EventGenerator.RandomEventHandler(RandomEvent);
eventGenerator2 = new EventGenerator(CQ, listBox2);
eventGenerator2.OnRandomEvent += new EventGenerator.RandomEventHandler(RandomEvent);
}
private void RandomEvent(object sender, IncomingConnectionEventArgs e)
{
string s = e.Property_Int.ToString()
+ " "
+ e.Property_String;
UpdateListbox(s, e.LB);
}
private void UpdateListbox(string argstring, ListBox argListBox)
{
if (InvokeRequired)
{
Invoke(new Action<string, ListBox>(UpdateListbox), new object[] { argstring, argListBox });
return;
}
int n;
bool b = false;
//do
//{
b = CQ.TryDequeue(out n);
//} while (!b);
argListBox.Items.Add(argstring);
argListBox.SelectedIndex = argListBox.Items.Count -1;
listBoxDeQueue.Items.Add(n.ToString());
listBoxDeQueue.SelectedIndex = listBoxDeQueue.Items.Count - 1;
}
private void button_Start_Click(object sender, EventArgs e)
{
Thread methodThread1 = new Thread(new ThreadStart(TheThread1));
methodThread1.Start();
Thread methodThread2 = new Thread(new ThreadStart(TheThread2));
methodThread2.Start();
}
private void TheThread2()
{
eventGenerator2.Start();
}
private void TheThread1()
{
eventGenerator1.Start();
}
private void button_Stop_Click(object sender, EventArgs e)
{
eventGenerator1.Stop();
eventGenerator2.Stop();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
eventGenerator1.Stop();
eventGenerator2.Stop();
}
}
IncomingConnectionEventArgs
class IncomingConnectionEventArgs : EventArgs
{
public System.Windows.Forms.ListBox LB;
public int Property_Int { get; set; }
public string Property_String { get; set; }
public IncomingConnectionEventArgs(int argInt, string argString,
System.Windows.Forms.ListBox lb)
{
LB = lb;
Property_Int = argInt;
Property_String = argString;
}
}
EventGenerator
class EventGenerator
{
public delegate void RandomEventHandler(
object sender,
IncomingConnectionEventArgs e);
public event RandomEventHandler OnRandomEvent;
public Random r = new Random();
public ListBox listBox;
public bool Generate = true;
public ConcurrentQueue<int> CQ;
public EventGenerator(ConcurrentQueue<int> argCQ, ListBox argListBox)
{
CQ = argCQ;
listBox = argListBox;
}
public void Start()
{
Generate = true;
while (Generate)
{
Thread.Sleep(r.Next(100, 2000));
RandomEvent();
}
}
public void Stop()
{
Generate = false; ;
}
public void RandomEvent()
{
if (OnRandomEvent == null)
{
return;
}
int n = r.Next(1000, 10000);
CQ.Enqueue(n);
IncomingConnectionEventArgs Args =
new IncomingConnectionEventArgs(n, "", listBox);
OnRandomEvent(this, Args);
}
}
The problem is with your use of Random. Unless you use a single instance of Random or explicitly seed each instance differently, the two threads calling Random.Next(...) will typically generate the same values.
A better way to seed your instance is this:
Random r = new Random(Guid.NewGuid().GetHashCode());
I am learning threading in C#, and I have a problem :
I have a list of items, and each item refreshes the value of one variable every second, thanks to a DispatcherTimer.
Then, I created a thread, with an infinite loop, and send this value.
Maybe the code will be better to understand.
Product :
public class Product : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void notifyPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private double price;
public double Price
{
get { return price; }
set
{
price = value;
notifyPropertyChanged("Price");
}
}
private Timer timer;
public Product(int time)
{
timer = new Timer(time);
timer.Elapsed += timer_Elapsed;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
Random r = new Random();
this.Price = Math.Round(r.NextDouble() * (maxPrice - minPrice) + minPrice, 2);
}
}
Main :
public MainWindow()
{
Thread thread;
InitializeComponent();
this.DataContext = this;
thread = new Thread(() => createServer(listGroupProduct));
thread.Start();
}
public static void createServer(ObservableCollection<GroupProducts> list)
{
string client = "";
try
{
IPAddress ipAdress = IPAddress.Parse("xxx.xxx.xx.xx");
TcpListener listener = new TcpListener(ipAdress, 1220);
listener.Start();
socket = listener.AcceptSocket();
while (true)
{
articlesString = list[0].Price.ToString();
byte[] bytes = new byte[list.Count * 50];
bytes = System.Text.Encoding.ASCII.GetBytes(articlesString.ToCharArray());
socket.Send(bytes);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
My problem is : the value send is always the same, but if I check the value in the main, the value changed...
Have you a solution ?
Declare private double price; as private volatile double price; since it's used by multiple threads.
You might want to read: http://www.andrewdenhertog.com/c/thread-safe-lock-volatile-and-interlock-in-c/
I have an app that has several methods that take a long time to complete. I am using a backgroundworker to run these methods and keep my UI responsive. My methods look something like
public void DoSomething()
{
while( HaveMoreWork )
{
// do work
}
}
Now i want the UI to be able to cancel this at any time so I have changed my methods to take a Backgroundworker like so
public void DoSomething(Backgroundworker worker)
{
while( HaveMoreWork && !worker.CancelationPending )
{
// do work
}
}
My question is, is there a better way to do this. Seems like passing a Backgroundwoker as an argument to all these methods is a bit messy. What is best practice for this?
I am using global variable
private BackgroundWorker _bwSearch = new BackgroundWorker();
private void InitializeBackgroundWorker()
{
_bwSearch = new BackgroundWorker();
_bwSearch.WorkerSupportsCancellation = true;
_bwSearch.DoWork += bwSearch_DoWork;
_bwSearch.RunWorkerCompleted += bwSearch_RunWorkerCompleted;
}
when clicked on stop button
private void btnCancel_Click(object sender, EventArgs e)
{
_bwSearch.Abort();
}
Updated:
Also I am using this simple helper class that is inherited from BackgroundWorker
public class AbortableBackgroundWorker : BackgroundWorker
{
private Thread _workerThread;
protected override void OnDoWork(DoWorkEventArgs e)
{
_workerThread = Thread.CurrentThread;
try
{
base.OnDoWork(e);
}
catch (ThreadAbortException)
{
e.Cancel = true;
Thread.ResetAbort();
}
}
public void Abort()
{
if (_workerThread != null)
{
_workerThread.Abort();
_workerThread = null;
}
}
}
public class DoSomethingService
{
private volatile bool _stopped = false;
public void Start(object socketQueueObject)
{
while (!_stopped)
{
...
}
}
public void Stop()
{
_stopped = true;
}
}
...
var doSomethingService = DoSomethingService();
doSomethingService.Start();
...
doSomethingService.Stop();
I have a working solution that reports progress & text to a progress bar and a label on the applications's main form. I have now moved my worker methods to a class to they are accessible across multiple forms etc.
Within the worker methods are BW.ReportProgress() statements that push back the progress and text to the BackgroundWorker in the main form.
To give a better idea here is the file layout:
MainScreen.cs
List repSelected = new List();
XMLandRar xXMLandRar = new XMLandRar();
private void Rarbtn_Click(object sender, EventArgs e)
{
GetReps();
//Run worker
if (!CreateRarBW.IsBusy)
{
CreateRarBW.RunWorkerAsync();
}
}
//Worker
private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
{
xXMLandRar.RarFiles(repSelected);
}
//Progress reporting
private void CreateRarBW_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progBar.Value = e.ProgressPercentage;
Statuslbl.Text = e.UserState.ToString();
}
Then my newly created Class that encompasses all of the worker methods and is to push progress to the main form.
XMLandRar.cs
public class XMLandRar
{
public void RarFiles(List repSelected)
{
int step = 100 / repSelected.Count();
int i = 0;
//Iterate through list and run rar for each
foreach (string rep in repSelected)
{
CreateRarBW.ReportProgress(i, "Raring files for " + rep);
DirectoryExists(rep);
ProcessRunner(rep);
i += step;
CreateRarBW.ReportProgress(i, "Raring files for " + rep);
}
}
}
The problem I am having is that in the XMLandRar class the CreateRarBW is not recognised (obviously) - how can I make a ReportProgress call to the BW in the main screen of the application?
Create an event in your XMLandRar class which you could subscribe to.
This way the XMLandRar class doesn't need to know or care about the UI or progressbar, it only cares about sending a message if anyone would listen. And there can also be more than one subscriber (let's say if you want to report to the background worker and a log, maybe)
Example:
private void Rarbtn_Click(object sender, EventArgs e)
{
GetReps();
//Run worker
if (!CreateRarBW.IsBusy)
{
// This should be done once, maybe in the contructor. Bind to new event.
xXMLandRar.ReportProgress += new EventHandler<XMLandRar.ProgressArgs>(xXMLandRar_ReportProgress);
CreateRarBW.RunWorkerAsync();
}
}
protected void xXMLandRar_ReportProgress(object sender, XMLandRar.ProgressArgs e)
{
// Call the UI backgroundworker
CreateRarBW.ReportProgress(e.Percentage, e.Message);
}
public class XMLandRar
{
// Event handler to bind to for reporting progress
public EventHandler<ProgressArgs> ReportProgress;
// Eventargs to contain information to send to the subscriber
public class ProgressArgs : EventArgs
{
public int Percentage { get; set; }
public string Message { get; set; }
}
public void RarFiles(List repSelected)
{
int step = 100 / repSelected.Count();
int i = 0;
//Iterate through list and run rar for each
foreach (string rep in repSelected)
{
// Report progress if somebody is listening (subscribed)
if (ReportProgress != null)
{
ReportProgress(this, new ProgressArgs { Percentage = i, Message = "Raring files for " + rep });
}
DirectoryExists(rep);
ProcessRunner(rep);
i += step;
// Report progress if somebody is listening (subscribed)
if (ReportProgress != null)
{
ReportProgress(this, new ProgressArgs { Percentage = i, Message = "Raring files for " + rep });
}
}
}
}
The sender object in the DoWork callback is the BackgroundWorker instance which is calling this callback.
This enables to use the instance and add it to your new XMLandRar class.
private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker.
xXMLandRar.RarFiles(repSelected, worker);
}
XMLandRar.cs
public class XMLandRar
{
public void RarFiles(List repSelected, BackgroundWorker worker)
{
// ...
}
}
Or you set the BackgroundWorkerinstance as a class property to the XMLandRar.
public class XMLandRar
{
protected BackgroundWorker mWorker;
public XMLandRar(BackgroundWorker worker) {
mWorker = BackgroundWorker;
}
public void RarFiles(List repSelected)
{
// Do something with {mWorker}
}
}
Or as mentioned in the comments, using events in the XMLandRar class.
XMLandRar.cs
public class XmlandRarCompletedEventArgs : EventArgs
{
public readonly bool Finished;
public readonly bool Canceled;
public XmlandRarCompletedEventArgs(bool finished)
{
Finished = finished;
Canceled = !finished;
}
}public class OnXmlandRarUpdateEventArgs : EventArgs
{
public readonly int Percentage;
public readonly string Message;
public XmlandRarCompletedEventArgs(int perc) :
this(perc, "") {
}
public XmlandRarCompletedEventArgs(int perc, string message)
{
Percentage = perc;
Message = message;
}
}
public delegate void OnXmlandRarDoWorkHandler(object o);
public delegate void OnXmlandRarUpdateHandler(object o, OnXmlandRarUpdateEventArgs args);
public delegate void OnXmlandRarCompleteHandler(object o, XmlandRarCompletedEventArgs args);
public class XMLandRar
{
public event OnXmlandRarDoWorkHandler OnDoWork;
public event OnXmlandRarUpdateHandler OnUpdate;
public event OnXmlandRarCompletedHandler OnComplete;
public void RarFiles(List repSelected)
{
TriggerDoWork();
int step = 100 / repSelected.Count();
int i = 0;
//Iterate through list and run rar for each
foreach (string rep in repSelected)
{
TriggerUpdate(i, "Raring files for " + rep);
DirectoryExists(rep);
ProcessRunner(rep);
i += step;
TriggerUpdate(i, "Raring files for " + rep);
}
TriggerComplete(true);
}
private void TriggerDoWork()
{
if (OnDoWork != null) {
OnDoWork(this);
}
}
private void TriggerUpdate(perc) {
}
if (OnUpdate != null) {
OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc));
}
private void TriggerUpdate(perc, string message)
{
if (OnUpdate != null) {
OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc, message));
}
}
private void TriggerComplete(bool finished)
{
if (OnComplete != null) {
OnComplete(this, new XmlandRarCompletedEventArgs(finished));
}
}
}
Usage:
private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker;
// Attach events to class
xXMLandRar.OnDoWork += delegate(object o) {
// ...
};
xXMLandRar.OnUpdate += delegate(object o, OnXmlandRarUpdateEventArgs args) {
// ...
};
xXMLandRar.OnComplete += delegate(object o, XmlandRarCompletedEventArgs args) {
// ...
};
xXMLandRar.RarFiles(repSelected, worker);
}
Hopefully without typos 'cause I'm in the office.
I have fixed errors in the code submitted and cleaned it up... This is a working sample that will help those that maybe couldn't understand the code since it was broken as it was... Although I would like to say that the intent and functionality of the code after it was cleaned up and enhanced is excellent.
This is working code that can get you started in your project for using a backGroundWorker thread for whatever you need.
Just modify this method -
public void RarFiles(List<string> repSelected)
To do whatever work you need. You will also have to modify the arguments you plan on using.. i.e. you may need a DataTable or some custom object...
You can modify the
public class OnXmlandRarUpdateEventArgs : EventArgs
For your needs.. that way when you get a callback.. you can update your main UI form with the changes made to those items..
You may need to do some tweaking.. but you see what i mean..
This is the Form Code.. Don't forget to create a button on 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;
namespace ThreadSample
{
public partial class Form1 : Form
{
List<string> repSelected = new List<string>();
XMLandRar xXMLandRar = new XMLandRar();
BackgroundWorker CreateRarBW = new BackgroundWorker();
public Form1()
{
InitializeComponent();
repSelected = new List<string> { "asdf", "asdfsd", "h;ljj" };
CreateRarBW.DoWork += new DoWorkEventHandler(CreateRarBW_DoWork);
}
private void Rarbtn_Click(object sender, EventArgs e)
{
//GetReps();
//Run worker
if (!CreateRarBW.IsBusy)
{
// This should be done once, maybe in the contructor. Bind to new event.
xXMLandRar.ReportProgress += new EventHandler<XMLandRar.ProgressArgs>(xXMLandRar_ReportProgress);
CreateRarBW.RunWorkerAsync();
}
}
protected void xXMLandRar_ReportProgress(object sender, XMLandRar.ProgressArgs e)
{
// Call the UI backgroundworker
CreateRarBW.ReportProgress(e.Percentage, e.Message);
}
//private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
//{
// var worker = sender as BackgroundWorker;
// xXMLandRar.RarFiles(repSelected, worker);
//}
private void CreateRarBW_DoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker;
// Attach events to class
xXMLandRar.OnDoWork += delegate(object o)
{
// ...
MessageBox.Show("Hey ... Something is going on over there in the classLib .. " + o);
};
xXMLandRar.OnUpdate += delegate(object o, OnXmlandRarUpdateEventArgs args)
{
// ...
//foreach (object oo in args)
{
MessageBox.Show("Hey ... Something is going on over there in the classLib .. Message is " + args.Message + " and Percentage is " + args.Percentage);
}
};
xXMLandRar.OnComplete += delegate(object o, XmlandRarCompletedEventArgs args)
{
MessageBox.Show("Hey ... Something is going on over there in the classLib .. Canceled is " + args.Canceled + " and Finished is " + args.Finished);
// ...
};
xXMLandRar.RarFiles(repSelected);//, worker);
}
}
}
This is the class code. You can just create a class in your current project... Keep in mind that the CreateRarBW object is a BackGroundWorker instance... (Wasn't included above..)
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading;
namespace ThreadSample
{
public class XmlandRarCompletedEventArgs : EventArgs
{
public readonly bool Finished;
public readonly bool Canceled;
public XmlandRarCompletedEventArgs(bool finished)
{
Finished = finished;
Canceled = !finished;
}
}
public class OnXmlandRarUpdateEventArgs : EventArgs
{
public readonly int Percentage;
public readonly string Message;
public OnXmlandRarUpdateEventArgs(int perc) : this(perc, "")
{
}
public OnXmlandRarUpdateEventArgs(int perc, string message)
{
Percentage = perc;
Message = message;
}
}
public delegate void OnXmlandRarDoWorkHandler(object o);
public delegate void OnXmlandRarUpdateHandler(object o, OnXmlandRarUpdateEventArgs args);
public delegate void OnXmlandRarCompleteHandler(object o, XmlandRarCompletedEventArgs args);
public class XMLandRar // : BackgroundWorker
{
// Event handler to bind to for reporting progress
public EventHandler<ProgressArgs> ReportProgress;
// Eventargs to contain information to send to the subscriber
public class ProgressArgs : EventArgs
{
public int Percentage { get; set; }
public string Message { get; set; }
}
public event OnXmlandRarDoWorkHandler OnDoWork;
public event OnXmlandRarUpdateHandler OnUpdate;
public event OnXmlandRarCompleteHandler OnComplete;
public void RarFiles(List<string> repSelected)
{
TriggerDoWork();
int step = 100 / repSelected.Count();
int i = 0;
//Iterate through list and run rar for each
foreach (string rep in repSelected)
{
TriggerUpdate(i, "Raring files for " + rep);
//DirectoryExists(rep);
//ProcessRunner(rep);
i += step;
TriggerUpdate(i, "Raring files for " + rep);
}
TriggerComplete(true);
}
private void TriggerDoWork()
{
if (OnDoWork != null)
{
OnDoWork(this);
}
}
private void TriggerUpdate(int perc)
{
if (OnUpdate != null)
{
OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc));
}
}
private void TriggerUpdate(int perc, string message)
{
if (OnUpdate != null)
{
OnUpdate(this, new OnXmlandRarUpdateEventArgs(perc, message));
}
}
private void TriggerComplete(bool finished)
{
if (OnComplete != null)
{
OnComplete(this, new XmlandRarCompletedEventArgs(finished));
}
}
}
}