I have a lock in my c# web app that prevents users from running the update script once it has started.
I was thinking I would put a notification in my master page to let the user know that the data isn't all there yet.
Currently I do my locking like so.
protected void butRefreshData_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ParameterizedThreadStart(UpdateDatabase));
t.Start(this);
//sleep for a bit to ensure that javascript has a chance to get rendered
Thread.Sleep(100);
}
public static void UpdateDatabase(object con)
{
if (Monitor.TryEnter(myLock))
{
Updater.RepopulateDatabase();
Monitor.Exit(myLock);
}
else
{
Common.RegisterStartupScript(con, AlreadyLockedJavaScript);
}
}
And I do not want to do
if(Monitor.TryEnter(myLock))
Monitor.Exit(myLock);
else
//show processing labal
As I imagine there is a slight possibility that it might display the notification when it isn't actually running.
Is there an alternative I can use?
Edit:
Hi Everyone, thanks a lot for your suggestions! Unfortunately I couldn't quite get them to work...
However I combined the ideas on 2 answers and came up with my own solution. It seems to be working so far but I have to wait for the process to complete...
Ok this seems to be working, I broke out the Repopule Method into it's own class.
public static class DataPopulation
{
public static bool IsUpdating = false;
private static string myLock = "My Lock";
private static string LockMessage = #"Sorry, the data repopulation process is already running and cannot be stopped. Please try again later. If the graphs are not slowly filling with data please contact your IT support specialist.";
private static string LockJavaScript = #"alert('" + LockMessage + #"');";
public static void Repopulate(object con)
{
if (Monitor.TryEnter(myLock))
{
IsUpdating = true;
MyProjectRepopulate.MyProjectRepopulate.RepopulateDatabase();
IsUpdating = false;
Monitor.Exit(myLock);
}
else
{
Common.RegisterStartupScript(con, LockJavaScript);
}
}
}
In master I do
protected void Page_Load(object sender, EventArgs e)
{
if (DataPopulation.IsUpdating)
lblRefresh.Visible = true;
else
lblRefresh.Visible = false;
}
(Given that you are aware of the race condition for displaying this notification just after processing stopped.... )
You could switch to a CountdownEvent. This works similarly to a ManualResetEvent, but also provides CurrentCount and IsSet properies, which could be used to determine if something is being processed.
How about just setting a volaltile bool property somewhere that indicates an active lock, perhaps via callback method?
Explore Autoresetevents and ManualResetevents. You can have the spawned thread set the event and check the event in the main thread to display the message.
butRefreshData_Click()
{
lock(myLock)
{
if (isbusy) {/*tell user*/}
}
}
UpdateDatabase(object con)
{
lock(myLock)
{
if (isbusy) {/*tell user*/ return;}
else {isbusy = true;}
}
Updater.RepopulateDatabase();
lock(myLock)
{
isBusy = false;
}
}
Note: You should probably wrap UpdateDatabase in a try-finally to avoid isBusy from being stuck true if an exception is thrown.
As I imagine there is a slight
possibility that it might display the
notification when it isn't actually
running.
There will always be the possibility you send the "Working..." message and then immediately the job is finished. What you have should logically work.
public static void UpdateDatabase(object con)
{
if (Monitor.TryEnter(myLock))
{
System.Diagnostics.Debug.WriteLine("Doing the work");
Thread.Sleep(5000);
Monitor.Exit(myLock);
System.Diagnostics.Debug.WriteLine("Done doing the work");
}
else
{
System.Diagnostics.Debug.WriteLine("Entrance was blocked");
}
}
Related
i have an application (.Net Framework 2.0!) where you can enter operations which will be executed at a given time.
Now i want to create a process which runs in background and does nothing else then waiting till the given time is reached and call the operation to run. The application should run things like making backup of specific parts of the computer, start updates, run batches, ... The backgroundworker will run over several month doing nothing else.
Using the code below would work but it seems a bit ugly. Is there any better solution?
while(true && !applicationClosing)
{
List<ExecProcess> processList = LoadStoredProcesses();
List<ExecProcess> spawnedProcesses = new List<ExecProcess>();
DateTime actualTime = DateTime.Now();
foreach(ExecProcess ep in processList)
{
if(ep.ExecutionTime < actualTime)
{
ep.Execute();
spawnedProcesses.Add(ep);
}
}
RemoveSpawnedProcesses(spawnedProcesses);
Thread.Sleep(1000);
}
Thank you verry much.
I would suggest using a Windows service which implements a timer that fires an event every n seconds. You can pickup your tasks from wherever you want, and queue them internally in the service and fire at given times. Just check the timestamps within the _executeTimer_Elapsed method. This is only a small sample, but it should be enough to get you started.
public class MyService : ServiceBase
{
private Timer _executeTimer;
private bool _isRunning;
public MyService()
{
_executeTimer = new Timer();
_executeTimer.Interval = 1000 * 60; // 1 minute
_executeTimer.Elapsed += _executeTimer_Elapsed;
_executeTimer.Start();
}
private void _executeTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!_isRunning) return; // logic already running, skip out.
try
{
_isRunning = true; // set timer event running.
// perform some logic.
}
catch (Exception ex)
{
// perform some error handling. You should be aware of which
// exceptions you can handle and which you can't handle.
// Blanket handling Exception is not recommended.
throw;
}
finally
{
_isRunning = false; // set timer event finished.
}
}
protected override void OnStart(string[] args)
{
// perform some startup initialization here.
_executeTimer.Start();
}
protected override void OnStop()
{
// perform shutdown logic here.
_executeTimer.Stop();
}
}
I'm developing an app where the app will ask a question to the user, a few actually - for instance asking if the user wants to rate the app. I need to run this method, but it greatly increases the app startup time. How can I run this in the background? I checked other questions on stack overflow without much help. The method that needs to be run in the background:
Called simply like this:
checkUserStats();
Method:
private void checkUserStats()
{
// Load settings from IsolatedStorage first
try
{
userRemindedOfRating = Convert.ToBoolean(settings["userRemindedOfRating"].ToString());
}
catch (Exception)
{
userRemindedOfRating = false;
}
try
{
wantsAndroidApp = Convert.ToBoolean(settings["wantsAndroidApp"].ToString());
}
catch (Exception)
{
wantsAndroidApp = false;
}
//Check if the user has added more 3 notes, if so - remind the user to rate the app
if (mainListBox.Items.Count.Equals(4))
{
//Now check if the user has been reminded before
if (userRemindedOfRating.Equals(false))
{
//Ask the user if he/she wants to rate the app
var ratePrompt = new MessagePrompt
{
Title = "Hi!",
Message = "I See you've used the app a little now, would u consider doing a review in the store? It helps a lot! Thanks!:)"
};
ratePrompt.IsCancelVisible = true;
ratePrompt.Completed += ratePrompt_Completed;
ratePrompt.Show();
//Save the newly edited settings
try
{
settings.Add("userRemindedOfRating", true);
settings.Save();
}
catch (Exception)
{
}
//Update the in-memory boolean
userRemindedOfRating = true;
}
else if (userRemindedOfRating.Equals(true))
{
// Do nothing
}
}
else
{
}
// Ask the user if he/she would like an android app
if (wantsAndroidApp.Equals(false))
{
// We haven't asked the user yet, ask him/her
var androidPrompt = new MessagePrompt
{
Title = "Question about platforms",
Message = "Hi! I just wondered if you wanted to have this app for android? If so, please just send me a quick email. If enough people wants it, I'll create it:)"
};
androidPrompt.IsCancelVisible = true;
androidPrompt.Completed += androidPrompt_Completed;
androidPrompt.Show();
//Save the newly edited settings
try
{
settings.Add("wantsAndroidApp", true);
settings.Save();
}
catch (Exception)
{
}
//Update the in-memory boolean
wantsAndroidApp = true;
}
else if (wantsAndroidApp.Equals(true))
{
// We have asked the user already, do nothing
}
}
I tried this now:
Using:
using System.ComponentModel;
Declaration:
BackgroundWorker worker;
Initialization:
worker = new BackgroundWorker();
worker.DoWork+=worker_DoWork;
Method:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
checkUserStats();
}
But it causes a System.UnauthorizedAccessException: Invalid cross-thread access in my app.xaml.cs
you could use a background worker thread and put your method call inside it
'The Silverlight BackgroundWorker class provides an easy way to run time-consuming operations on a background thread. The BackgroundWorker class enables you to check the state of the operation and it lets you cancel the operation.
When you use the BackgroundWorker class, you can indicate operation progress, completion, and cancellation in the Silverlight user interface. For example, you can check whether the background operation is completed or canceled and display a message to the user.'
You basically just need to initialize a backgroundworker object and subscribe to its DoWork event.
And the remedy for your exception
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
Dispatcher.BeginInvoke(() =>
{
checkUserStats();
});
}
just give a look at this msdn article
and one more article.
I have a BackgroundWorker_DoWork method in my client application which sends a tcp message using NetworkComms.Net to a server and check for an answer.
The method for that last part is
NetworkComms.AppendGlobalIncomingPacketHandler
where I can verify if the answer has a certain type and if yes, invoke another method to handle the answer message itself.
What I want to do is to stop the BackgroundWorker from within the handler, but I can't figure out how. Any help is greatly appreciated, as I'm very new to Object-Oriented Programming and I'm probably missing something fundamental.
Here's the relevant piece of code:
private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
{
if (backgroundWorker2.CancellationPending)
{
e.Cancel = true;
return;
}
string serverIP = entr_serverIP.Text;
int serverPORT;
int.TryParse(entr_serverPORT.Text, out serverPORT);
bool loop = true;
while (loop == true)
{
if (backgroundWorker2.CancellationPending)
{
e.Cancel = true;
return;
}
try
{
NetworkComms.SendObject("Message", serverIP, serverPORT, "status");
NetworkComms.AppendGlobalIncomingPacketHandler<string>("ReturnHere", DoSomething2);
}
catch(DPSBase.CommsException ex2)
{
MessageBox.Show(ex2.ToString());
e.Cancel = true;
return;
}
Thread.Sleep(100);
}
}
private static void DoSomething2(PacketHeader header, Connection connection, string message)
{
bool svAlarmSent = false;
while (svAlarmSent == false)
{
if (message == "KEYWORD")
{
string svInfo = connection.ConnectionInfo.RemoteEndPoint.ToString();
Form4 form4 = new Form4("KEYWORD", null, svInfo);
form4.Show();
svAlarmSent = true;
backgroundWorker2.CancelAsync();
loop = false;
}
}
}
The two last lines of the above code don't work because the CancelAsync method and the loop variable don't exist in that context.
The first step to fixing this is to enable cancellation from the DoSomething2 method. To do this it needs access to the backgroundWorker2 variable. This is a field (attribute), hence you can give it access by making the method non-static:
private void DoSomething2(PacketHeader header, Connection connection, string message)
The next step is to simple remove the access of the loop value from DoSomething2. The responsibility of this method is to signal the cancellation only. It is the job of the backgroundWorker2_DoWork method to respond to this cancellation.
In fact the loop variable doesn't even need to be set. Once CancelAsync is called the following conditional will be met:
if (backgroundWorker2.CancellationPending)
{
e.Cancel = true;
return;
}
By virtue of returning this code will break the while loop by itself.
Overall I would say that this isn't really the intended use of a BackgroundWorker though. Cancellation is supposed to be used to allow the user, or some operation, to signal that the background task should cancel the work and return without completing (if possible). In this case you are using cancellation to signal the succesful completion of the code. This works but is somewhat of an unintended use case.
I am not sure exactly what you are asking, but here is an easy example how to handle background workers.
private readonly bool _shouldStop;
public void Start()
{
Thread workerThread = new Thread(DoWork);
workerThread.IsBackground = true;
workerThread.Start();
}
public void DoWork()
{
while (!_shouldStop)
{
//work
}
}
public void RequestStop()
{
_shouldStop = true;
}
to start the worker just call Start() and to stop it call RequestStop()
http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
I have a button that on click event I get some information from the network.
When I get information I parse it and add items to ListBox. All is fine, but when I do a fast double-click on button, it seems that two background workers are running and after finishing all work, items in the list are dublicated.
I want to do so that if you click button and the proccess of getting information is in work, this thread is stopping and only after first work is completed the second one is beginning.
Yes, I know about AutoResetEvent, but when I used it it helped me only one time and never more. I can't implement this situation and hope that you will help me!
Now I even try to make easier but no success :( : I added a flag field(RefreshDialogs)(default false), when the user clicks on button, if flag is true(it means that work is doing), nothing is doing, but when flag field is set to false, all is fine and we start a new proccess.
When Backgroundwork completes, I change field flag to false(it means that user can run a new proccess).
private void Message_Refresh_Click(object sender, EventArgs e)
{
if (!RefreshDialogs)
{
RefreshDialogs = true;
if (threadBackgroundDialogs.WorkerSupportsCancellation)
{
threadBackgroundDialogs.CancelAsync();
}
if (!threadBackgroundDialogs.IsBusy)
{
downloadedDialogs = 0;
threadBackgroundDialogs = new BackgroundWorker();
threadBackgroundDialogs.WorkerSupportsCancellation = true;
threadBackgroundDialogs.DoWork += LoadDialogs;
threadBackgroundDialogs.RunWorkerCompleted += ProcessCompleted;
threadBackgroundDialogs.RunWorkerAsync();
}
}
}
void ProcessCompleted(object sender, RunWorkerCompletedEventArgs e)
{
RefreshDialogs = false;
}
So you want to keep the second process running while the first works, but they shouldn't disturb each other? And after the first one finishes the second one continues?
Crude way: While loop:
if (!RefreshDialogs)
{
RefreshDialogs = true;
this becomes:
while(RefreshDialogs)
{
}
RefreshDialogs = true;
After you set it false the second process wwill jump out of the while. (Note this is extremly inefficent since both processes will be running all the time, i'm pretty sure the second one will block the first one, but with multitasking now it shouldn't, if it block use a Dispatcher.Thread)
Elegant way: Use A Semaphore
http://msdn.microsoft.com/de-de/library/system.threading.semaphore%28v=vs.80%29.aspx
If you find it impossible to have both processes running at the same time, or want another way:
Add an Array/List/int and when the second process notices there is the first process running, like with your bool, increase your Added variable, and at the end of the process, restart the new process and decrese the variable:
int number;
if (!RefreshDialogs)
{
RefreshDialogs = true;
your code;
if(number > 0)
{
number--;
restart process
}
}
else
{
number++;
}
I have to admit, i like my last proposal the most, since its highly efficent.
Make your thread blocking. That is easy;
lock(someSharedGlobalObject)
{
Do Work, Exit early if cancelled
}
This way other threads will wait until the first thread releases the lock. They will never execute simultaneously and silently wait until they can continue.
As for other options; why not disable the button when clicked and re-enable it when the backgroundworker completes. Only problem is this does not allow for cancelling the current thread. The user has to wait for it to finish. It does make any concurrency go away very easily.
How about this approach?
Create a request queue or counter which will be incremented on every button click. Every time that count is > 0. Start the background worker. When the information comes, decrement the count and check for 0. If its still > 0 restart the worker. In that your request handler becomes sequential.
In this approach you may face the problem of continuous reference of the count by two threads, for that you may use a lock unlock condition.
I hav followed this approach for my app and it works well, hope it does the same for you.
I'm not an Windows Phone expert, but as I see it has support for TPL, so following code would read nicely:
private object syncRoot =new object();
private Task latestTask;
public void EnqueueAction(System.Action action)
{
lock (syncRoot)
{
if (latestTask == null)
latestTask = Task.Factory.StartNew(action);
else
latestTask = latestTask.ContinueWith(tsk => action());
}
}
Use can use semaphores
class TheClass
{
static SemaphoreSlim _sem = new SemaphoreSlim (3);
static void Main()
{
for (int i = 1; i <= 5; i++)
new Thread (Enter).Start (i);
}
static void Enter (object name)
{
Console.WriteLine (name + " wants to enter");
_sem.Wait();
Console.WriteLine (name + " has entered!");
Thread.Sleep (1000 * (int) name );
Console.WriteLine (name + " is leaving");
_sem.Release(); }
}
}
I found the solution and thanks to #Giedrius. Flag RefreshingDialogs is set to true only when proccess is at the end, when I added items to Listbox. The reason why I'am using this flag is that state of process changes to complete when the asynchronous operation of getting content from network(HttpWebRequest, method BeginGetRequestStream) begins, but after network operaion is complete I need to make UI operations and not only them(parse content and add it to Listbox)My solution is:
private object syncRoot = new object();
private Task latestTask;
public void EnqueueAction(System.Action action)
{
lock (syncRoot)
{
if (latestTask == null)
{
downloadedDialogs = 0;
latestTask = Task.Factory.StartNew(action);
}
else if(latestTask.IsCompleted && !RefreshingDialogs)
{
RefreshingDialogs = true;
downloadedDialogs = 0;
latestTask = Task.Factory.StartNew(action);
}
}
}
private void Message_Refresh_Click(object sender, EventArgs e)
{
Action ac = new Action(LoadDialogs2);
EnqueueAction(ac);
}
I have a form with 2 comboboxes on it. And I want to fill combobox2.DataSource based on combobox1.Text and combobox2.Text (I assume that the user has completed input in combobox1 and is in the middle of inputting in combobox2). So I have an event handler for combobox2 like this:
private void combobox2_TextChanged(object sender, EventArgs e)
{
if (cmbDataSourceExtractor.IsBusy)
cmbDataSourceExtractor.CancelAsync();
var filledComboboxValues = new FilledComboboxValues{ V1 = combobox1.Text,
V2 = combobox2.Text};
cmbDataSourceExtractor.RunWorkerAsync(filledComboboxValues );
}
As far as building DataSource is time-consuming process (it creates a request to database and executes it) I decided that it's better to perform it in another process using BackgroundWorker. So there's a scenario when cmbDataSourceExtractor hasn't completed its work and the user types one more symbol. In this case I get an exception on this line
cmbDataSourceExtractor.RunWorkerAsync(filledComboboxValues ); about that BackgroundWorker is busy and cannot perform several actions in the same time.
How to get rid of this exception?
CancelAsync doesn't actually abort your thread or anything like that. It sends a message to the worker thread that work should be cancelled via BackgroundWorker.CancellationPending. Your DoWork delegate that is being run in the background must periodically check this property and handle the cancellation itself.
The tricky part is that your DoWork delegate is probably blocking, meaning that the work you do on your DataSource must complete before you can do anything else (like check for CancellationPending). You may need to move your actual work to yet another async delegate (or maybe better yet, submit the work to the ThreadPool), and have your main worker thread poll until this inner worker thread triggers a wait state, OR it detects CancellationPending.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.cancelasync.aspx
http://www.codeproject.com/KB/cpp/BackgroundWorker_Threads.aspx
If you add a loop between the CancelAsync() and the RunWorkerAsync() like so it will solve your problem
private void combobox2_TextChanged(object sender, EventArgs e)
{
if (cmbDataSourceExtractor.IsBusy)
cmbDataSourceExtractor.CancelAsync();
while(cmbDataSourceExtractor.IsBusy)
Application.DoEvents();
var filledComboboxValues = new FilledComboboxValues{ V1 = combobox1.Text,
V2 = combobox2.Text};
cmbDataSourceExtractor.RunWorkerAsync(filledComboboxValues );
}
The while loop with the call to Application.DoEvents() will hault the execution of your new worker thread until the current one has properly cancelled, keep in mind you still need to handle the cancellation of your worker thread. With something like:
private void cmbDataSourceExtractor_DoWork(object sender, DoWorkEventArgs e)
{
if (this.cmbDataSourceExtractor.CancellationPending)
{
e.Cancel = true;
return;
}
// do stuff...
}
The Application.DoEvents() in the first code snippet will continue to process your GUI threads message queue so the even to cancel and update the cmbDataSourceExtractor.IsBusy property will still be processed (if you simply added a continue instead of Application.DoEvents() the loop would lock the GUI thread into a busy state and would not process the event to update the cmbDataSourceExtractor.IsBusy)
You will have to use a flag shared between the main thread and the BackgroundWorker, such as BackgroundWorker.CancellationPending. When you want the BackgroundWorker to exit, just set the flag using BackgroundWorker.CancelAsync().
MSDN has a sample: http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.cancellationpending.aspx
MY example . DoWork is below:
DoLengthyWork();
//this is never executed
if(bgWorker.CancellationPending)
{
MessageBox.Show("Up to here? ...");
e.Cancel = true;
}
inside DoLenghtyWork :
public void DoLenghtyWork()
{
OtherStuff();
for(int i=0 ; i<10000000; i++)
{ int j = i/3; }
}
inside OtherStuff() :
public void OtherStuff()
{
for(int i=0 ; i<10000000; i++)
{ int j = i/3; }
}
What you want to do is modify both DoLenghtyWork and OtherStuff() so that they become:
public void DoLenghtyWork()
{
if(!bgWorker.CancellationPending)
{
OtherStuff();
for(int i=0 ; i<10000000; i++)
{
int j = i/3;
}
}
}
public void OtherStuff()
{
if(!bgWorker.CancellationPending)
{
for(int i=0 ; i<10000000; i++)
{
int j = i/3;
}
}
}
The problem is caused by the fact that cmbDataSourceExtractor.CancelAsync() is an asynchronous method, the Cancel operation has not yet completed when cmdDataSourceExtractor.RunWorkerAsync(...) exitst. You should wait for cmdDataSourceExtractor to complete before calling RunWorkerAsync again. How to do this is explained in this SO question.
My answer is a bit different because I've tried these methods but they didn't work. My code uses an extra class that checks for a Boolean flag in a public static class as the database values are read or where I prefer it just before an object is added to a List object or something as such. See the change in the code below. I added the ThreadWatcher.StopThread property. for this explation I'm nog going to reinstate the current thread because it's not your issue but that's as easy as setting the property to false before accessing the next thread...
private void combobox2_TextChanged(object sender, EventArgs e)
{
//Stop the thread here with this
ThreadWatcher.StopThread = true;//the rest of this thread will run normally after the database function has stopped.
if (cmbDataSourceExtractor.IsBusy)
cmbDataSourceExtractor.CancelAsync();
while(cmbDataSourceExtractor.IsBusy)
Application.DoEvents();
var filledComboboxValues = new FilledComboboxValues{ V1 = combobox1.Text,
V2 = combobox2.Text};
cmbDataSourceExtractor.RunWorkerAsync(filledComboboxValues );
}
all fine
private void cmbDataSourceExtractor_DoWork(object sender, DoWorkEventArgs e)
{
if (this.cmbDataSourceExtractor.CancellationPending)
{
e.Cancel = true;
return;
}
// do stuff...
}
Now add the following class
public static class ThreadWatcher
{
public static bool StopThread { get; set; }
}
and in your class where you read the database
List<SomeObject>list = new List<SomeObject>();
...
if (!reader.IsDbNull(0))
something = reader.getString(0);
someobject = new someobject(something);
if (ThreadWatcher.StopThread == true)
break;
list.Add(something);
...
don't forget to use a finally block to properly close your database connection etc. Hope this helps! Please mark me up if you find it helpful.
In my case, I had to pool database for payment confirmation to come in and then update WPF UI.
Mechanism that spins up all the processes:
public void Execute(object parameter)
{
try
{
var url = string.Format("{0}New?transactionReference={1}", Settings.Default.PaymentUrlWebsite, "transactionRef");
Process.Start(new ProcessStartInfo(url));
ViewModel.UpdateUiWhenDoneWithPayment = new BackgroundWorker {WorkerSupportsCancellation = true};
ViewModel.UpdateUiWhenDoneWithPayment.DoWork += ViewModel.updateUiWhenDoneWithPayment_DoWork;
ViewModel.UpdateUiWhenDoneWithPayment.RunWorkerCompleted += ViewModel.updateUiWhenDoneWithPayment_RunWorkerCompleted;
ViewModel.UpdateUiWhenDoneWithPayment.RunWorkerAsync();
}
catch (Exception e)
{
ViewModel.Log.Error("Failed to navigate to payments", e);
MessageBox.Show("Failed to navigate to payments");
}
}
Mechanism that does checking for completion:
private void updateUiWhenDoneWithPayment_DoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(30000);
while (string.IsNullOrEmpty(GetAuthToken()) && !((BackgroundWorker)sender).CancellationPending)
{
Thread.Sleep(5000);
}
//Plug in pooling mechanism
this.AuthCode = GetAuthToken();
}
Mechanism that cancels if window gets closed:
private void PaymentView_OnUnloaded(object sender, RoutedEventArgs e)
{
var context = DataContext as PaymentViewModel;
if (context.UpdateUiWhenDoneWithPayment != null && context.UpdateUiWhenDoneWithPayment.WorkerSupportsCancellation && context.UpdateUiWhenDoneWithPayment.IsBusy)
context.UpdateUiWhenDoneWithPayment.CancelAsync();
}
I agree with guys. But sometimes you have to add more things.
IE
1) Add this worker.WorkerSupportsCancellation = true;
2) Add to you class some method to do the following things
public void KillMe()
{
worker.CancelAsync();
worker.Dispose();
worker = null;
GC.Collect();
}
So before close your application your have to call this method.
3) Probably you can Dispose, null all variables and timers which are inside of the BackgroundWorker.