Call BackgroundWorker from static method - c#

it's the first question I ask so please be tolerant if I do something wrong.
I am writing a software to read data from a serial port a then use it to update the status of a static list of objects. Every data I receive is a communication of a wireless node and it represents its status. I solved the reading part and I am handling the search and update part.
I would like to use the background worker to search the element in the list and then update it, assuring the user a clean and smooth UI. The problem is that I read the bytes through a static function, and from that static function I should call the backgroundworker to perform the task. I read on the dotnetperls guide that "RunWorkerAsync can be called anywhere in your code.", but when I try to call it from the static function, Visual Studio doesn't let me do it.
Can anyone help me?
[edit: code added]
This is the extract of my static method:
public static void Add(Byte[] received)
{
List<byte[]> messages = new List<byte[]>();
int lastdollars = 0;
byte[] tempmess = new byte[20]; //The message is 20 digits
lock (BufferLock)
{
//I add the last bytes to the buffer (it's a list of bytes)
Buffer.AddRange(received);
if (Buffer.Count < TOTALMESSAGELENGTH) return;
String temp = Encoding.UTF8.GetString(Buffer.ToArray());
//I check the buffer to look for complete messages (there are tokens at the start and at the end
for (int i = 0; i <= (temp.Length - TOTALMESSAGELENGTH + 1); i++)
{
if ((temp.Length > i + TOTALMESSAGELENGTH) &&
(temp.Substring(i, TOKENLENGTH) == STARTTOKEN) &&
(temp.Substring((i + TOKENLENGTH + MESSAGELENGTH), TOKENLENGTH) == ENDTOKEN))
{
//if I find a message, I put it into the list of messages, I save its position and I continue to look for other messages
tempmess = Encoding.UTF8.GetBytes(temp.Substring(i, TOTALMESSAGELENGTH));
messages.Add(tempmess);
lastdollars = i;
i += TOTALMESSAGELENGTH - 1;
}
}
if (messages.Count == 0)
return;
//I delete the buffer that I'm using and I need to call the background worker
Buffer.RemoveRange(0, (lastdollars + TOTALMESSAGELENGTH));
}
worker.RunWorkerAsync(messages); //Error: An object is required for the non-static field, method, or property 'namespace.Form1.worker'
}
I tried both to define manually the backgroundworker with:
private readonly BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
and adding it through the Toolbox, but the result is the same.

You cannot access instance variables in static methods. Hence the error. Try and make the BackgroundWorker instance static. Something like the following.
private readonly static BackgroundWorker worker = new BackgroundWorker();
Not very sure if this will not break any other of your code.
Hope this helps.

This doesn't really have anything to do with BackgroundWorker or any specific class. It is just how the C# language works.
You can't access non-static members from a static function. A static function has no implicit this parameter that makes it run against a particular instance of the class. You can run it without ever creating any instances of the class.
This worker
private readonly BackgroundWorker worker = new BackgroundWorker();
will be created once for each instance of the class. But you can call the Add function without having any instances.
For example, this doesn't work for the same reason:
class Adder
{
public int sum = 0;
public static void Add(int x)
{
sum += x; // can't reference "sum" from static method!
}
}
...
Adder.Add(5)
but this works:
class Adder
{
public int sum = 0;
public void Add(int x) // no longer static
{
sum += x; // this refers to the "sum" variable of this particular instance of Adder
}
}
...
var adder = new Adder();
adder.Add(5);
and this also works (but differently!):
class Adder
{
public static int sum = 0; // we made sum static (there is exactly one, instead of a separate sum for each instance)
public static void Add(int x)
{
sum += x; // this refers to the static sum variable
}
}
...
Adder.Add(5);

Related

BackgroundWorker randomly creating instances of objects in C#

Pretty much I am trying to a make a stimulation of a larger app but as for now this will do to test things out so I tried to make it as dynamic(real world) as possible. So I have a class called Event which only has fields getters and setters methods, this is the class i want to make instances of objects from the backgroundworker. I have looked at some generic examples but they do not seem to be of great help because they are all based on a GUI app, mine is a console app.
Anyway as soon as the class Events is called from the main class(assuming the user provided the correct input) one event is created by default
class Events
{
BackgroundWorker bw = new BackgroundWorker();
private Event newEvent;
private List<Event> events = new List<Event>();
private int listIndex = 0;
public Events()
{
generateEvent(); //generate first event as soon as user initiates
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler(bw_doWork);
bw.RunWorkerAsync();
}
private void bw_doWork(object sender, DoWorkEventArgs e)
{
int sleepTime = newEvent.random.Next(1000,5000); //events randomly created between 1 to 5 seconds
BackgroundWorker worker = sender as BackgroundWorker;
while (listIndex <= 15)
{
generateEvent();
System.Threading.Thread.Sleep(sleepTime);
}
}
private void generateEvent()
{
newEvent = new Event();
this.addEvent(newEvent);
}
private void addEvent(Event e){
//check uniqueness and reassign value if necessary then add to the list
e.setIdentifier(checkUniqueness(e.getIdentifier()));
e.setX(checkUniqueness(e.getX()));
e.setY(checkUniqueness(e.getY()));
events.Add(newEvent);
listIndex++;
}
private int checkUniqueness(int num){
foreach(Event eve in events){
if ((num == eve.getIdentifier()) || //event identifier must be unique
(num == eve.getX() && num == eve.getY())) //event x,y locations must hold one event
{
return checkUniqueness(num = newEvent.random.Next());//generate a new number for identifier
}
}
return num;
}
public List<Event> getEvents()
{
return events;
}
public int getIndex()
{
return listIndex;
}
}
however the backgroundworker class doesnt generate more events as the app is running which is what I need help with because I spent much time on it but I cant seem to get it done. Also when the events are created from the backgroundworker I want to report it(basically just add it to the List and call a method from the main class to update the number of events available) which again I dont know how to do because all the examples are based on GUIs.
Any help much appreciated unless backgroundWorker does not work on console applicatons?
Thanks in advance.

(C# Value Doesnt Change) Modifiying Static Variables from Static Callback Method

Hello i want to ask how to modifiying value static variable from static callback, and read value again. I need to stop while looping when value from static variable change. This is my code.
The problem is value from stepControlEx remain same, it doesnt change when another callback run again and modify the value. It makes my looping stuck and cannot end.
Thanks for helping
Private static int stepControl = 0;
Private static int stepControlEx
{
get { return stepControl;}
set { stepControl = value;}
}
Private static void CallbackHandle (Object object)
{
If (object == 0)
{
stepControlEx = 0;
While (stepControlEx == 0)
{
//do events
//stop when stepControl Change
}
}
Else If (object == 1)
{
stepControlEx = 1;
While (stepControlEx == 1)
{
//do events
//stop when stepControl Change
}
}
}
EDITED (SOLVED):
I tottaly change the algorithm and use thread that process data from queue. Callback function only enqueue input to queue and thread dequeue input to processing, now step control doesn't need as global variable. Thank you
Your code looks ambiguous. But I have only one comment for your code. If you have a static variable and shared among multiple threads, you need to lock the variable while changing it.
I think you get deadlocks that is why the loop never ends.
Anytime you assign any static variable in a multi-threading environment. you need to to this:
lock (new object())
{
stepControlEx = 0;
}

background/Asynchronous process using Threading or Delegate

At My website
1. After filling form Inserting that record in SQL database
2. In Next Line I take some class object then send to Matching with other record
3. In matching application taking so much time
Now I have decided I will put matching process in background/Asynchronous by using Threading or Delegate
My Previous code was:
1. Inserting all information in database
objclsBbDAL.InsertAcquirePrvider(objAcqProvBL);
2. Matching related record with other record in database
clsMatchMakingDAL objclsMatchMakingDAL = new clsMatchMakingDAL();
objclsMatchMakingDAL.AcquireMatch(objAcqProvBL);
Q 1. Which one is best way to run process in background/Asynchronous - Threading or Delegate
Now I am using Threading:
objclsBbDAL.InsertAcquirePrvider(objAcqProvBL);
//Threading
CallMatchMakingOnDiffThread(objAcqProvBL);
private void CallMatchMakingOnDiffThread(clsAcquireProviderBL objAcqPro)
{
clsMatchMakingDAL objclsMatchMakingDAL = new clsMatchMakingDAL();
Thread objThread = new Thread(() => objclsMatchMakingDAL.AcquireMatch(objAcqPro));
objThread.Start();
}
Q2. How can do this task with Delegate?
Delegates are like callbacks, you use them to notify that an asynchronous task has been completed, meaning the thread needs to call an event, which should have a delegate hooked onto it.
For example:
public struct ThreadData
{
public int handle;
public string details;
public ThreadData(int handle, string details)
{
this.handle = handle;
this.details = details;
}
}
public class ThreadWorker
{
private List<Thread> threads = new List<Thread>();
public int BeginAsyncWork(string details)
{
Thread thread = new Thread(new ParameterizedThreadStart(ThreadMethod));
threads.Add(thread);
thread.Start(new ThreadData(threads.Count - 1, details));
return threads.Count - 1;
}
private void ThreadMethod(object parameter)
{
ThreadData data = (ThreadData)parameter;
Console.WriteLine(data.details);
if (ThreadFinished != null) { ThreadFinished(data.handle); }
}
public delegate void ThreadEndDelegate(int handle);
public event ThreadEndDelegate ThreadFinished;
}
public static class Program
{
private static int[] handles;
public static void Main()
{
handles = new int[4];
ThreadWorker worker = new ThreadWorker();
worker.ThreadFinished += new ThreadWorker.ThreadEndDelegate(OnThreadFinished);
for (int i = 0; i < 4; i++)
{
handles[i] = worker.BeginAsyncWork("working: " + i);
}
Console.ReadKey();
}
private static void OnThreadFinished(int handle)
{
Console.WriteLine("thread: " + handle + " finished");
handles[handle] = 0;
}
}
It's long winded but it allows for full control over your threads.
EDIT:
Untested code. The shortest possible solution I could think of.
objclsBbDAL.InsertAcquirePrvider(objAcqProvBL);
//Threading
CallMatchMakingOnDiffThread(objAcqProvBL);
private void OnMatchAcquired(object match)
{
//do work with found match
}
private event Action<object> MatchAcquired = new Action<object>(OnMatchAcquired);
private void CallMatchMakingOnDiffThread(clsAcquireProviderBL objAcqPro)
{
clsMatchMakingDAL objclsMatchMakingDAL = new clsMatchMakingDAL();
Thread objThread = new Thread(
() => object match = (object)objclsMatchMakingDAL.AcquireMatch(objAcqPro); if(ThreadComplete!=nil){MatchAcquired(match);}
);
objThread.Start();
}
You can not do background processing with only a delegate.
A delegate is totally different from a thread or an asynchronous process.
You can understand a delegate as a pointer to a function.
Threads use delegates to execute a certain function but delegates alone are not any kind of background execution.
Doing what you mentioned up-there would run the process in background, but you have to know the costs for running the operation in background and in this way. You also need to know if it does really needs to be run in background or it only needs optimization.
The easyest way (for me at least) is to use a delegate and BeginInvoke, which will return immediately and for which you can supply a callback that is executed when the delegate is finished.
More info on MSDN.
In your sample code I do not see, that you need to be notified, when the operation is finished so you could do something like this:
new Action(() =>
{
clsMatchMakingDAL objclsMatchMakingDAL = new clsMatchMakingDAL();
objclsMatchMakingDAL.AcquireMatch(objAcqPro);
}).BeginInvoke(null, null);
This would execute the matching functionality on another thread that is managed by .Net for you. If you need to be notified on completion, then the first argument to the BeginInvoke call could be another delegate to handle the completion event.

Send a reference to a variable instead of it's value

I have a function that does a long task and I want to update a variable somewhere else occasionally with status updates. (If there is a better method for doing this, that's fine too) I'm writing a library and this code might be called several times at once so creating another variable in the same class that stores the variable isn't an option. Here is what my code might look like:
public static bool Count(int Progress, int CountToWhat) {
for (int i = 0; i < CountToWhat; i++) {
Progress = CountToWhat / i; // This is how I'd like to update the value, but obviously this is wrong
Console.WriteLine(i.ToString());
}
}
This is not a good way of providing updates to your callers.
Better you define one ore more events in your class library (like OnError, OnProgress, etc.).
You can raise, for example, OnProgress when you want to notify progress in a certain operation:
for (int i = 0; i < CountToWhat; i++) {
OnProgress(CountToWhat / i);
Console.WriteLine(i.ToString());
}
This is a much better way of doing it, especially when notifying from worker threads.
Change the signature to:
public static bool Count(ref int Progress, int CountToWhat)
And when you call it, use the ref keyword before the variable that you pass in as the first argument.
You can use
int Progress = 0;
public static bool Count(ref int Progress, int CountToWhat)
{
....
}
Or
int Progress; //without init
public static bool Count(out int Progress, int CountToWhat)
{
....
}
A better way might be to pass an Action<int> delegate to be called to report progress:
public static bool Count(int CountToWhat, Action<int> reportProgress)
{
for (int i = 0; i < CountToWhat; i++)
{
var progress = CountToWhat / i;
reportProgress(progress);
Console.WriteLine(i.ToString());
}
}
then you'd use it like:
Count(100, p => currentProgress = p);
You could also use the BackgroundWorker class to run your long running task, and utilize its ProgressChanged event.

Updating progress bar from a threadpool c#

I have trying to process some data using multithreading where I am using threadpool to generate threads equal to the number of cores(Limited to .NET 2.0 to 3.5 so cant use TPL).
All my threads execute the same function operating in different parts of my data.
My problem is I am unable to update the progress bar from the threads of the threadpool. Found solutions such as invoke and Background worker but could not really understand how to use them please help me out how to use them.
my code looks like
private static float[] inpdat=new float[1000];//The input array to process
//The spawned threads
public void dowork(object o)
{
int np = (int)o;
for(int i=np;i<inpdat.length;i=i+Environment.ProcessorCount)
{
//do some processing
if(np==0)
{
//update progress bar here
}
}
}
//The main thread
for (int npou = 0; npou < numproc; npou++)
{
resetEvents[npou] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(dowork), npou);
PetrelLogger.InfoOutputWindow("manual reset event set");
}
Speed is of paramount importance to me so would be very helpful if the cross thread calling takes up minimum time.
Thanks
Here is an example:
ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
{
// worker method implementation
.....
progressBar1.Invoke(new MethodInvoker(() => progressBar1.Value = 20));
}));
There is a little you can do with updating user controls, in your case Progress bar.
Add your form as the input parameter, or add some callback interface for the results, that your form will implement:
interface IMyCallback
{
void Progress(int progress);
}
In form implementation add following code:
void Progress(int Progress)
{
if(this.InvokeRequired)
{
this.BeginInvoke(new ParametrizedThreadStart(Inv_Progress), Progress);
}
else
{
Inv_Progress(Progress);
}
}
void Inv_Progress(object obj)
{
int progress = obj as int;
// do your update progress bar work here
}
Now you can do following:
public void dowork(object o)
{
int np = (int)o;
for(int i=np;i<inpdat.length;i=i+Environment.ProcessorCount)
{
//do some processing
if(np==0)
{
myCallback.Progress(0);
}
}
}
A standard invoke is probably easiest, and you can use an anonymous delegate to make it cleaner.
int n = 5;
myProgressBar.Invoke(
delegate
{
myProgressBar.Value = n;
}
);
Keep in mind that in certain scenarios (e.g. looped use of this delegate from within one thread) you may need to declare a delegate and pass the value into it as a parameter. If you don't, you can get strange behaviour with locals. This is the case for use of anonymous methods and the Action class, too.

Categories