private static bool Created;
private static System.Threading.Mutex PaintGuard = new System.Threading.Mutex(false, "MonkeysUncleBob", out Created);
//Function that is attached to each pages "LayoutUpdated" call.
private async void AnyPageLayoutUpdated(object sender, object e)
{
if (Created)
{
PaintGuard.WaitOne();
try
{
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
LCDDriver.ILI9488.PaintScreen(sender);
});
}
catch (Exception f)
{
}
finally
{
PaintGuard.ReleaseMutex();
}
}
}
The problem is that somehow multiple threads can enter into the code still.
I have verified this by using the debugger, and I can see multiple threads entering into the try before executing the finally.
I must be using it wrong.
await is not compatible with Mutex. You can use an async-compatible mutex like SemaphoreSlim or the AsyncLock that I have as part of my AsyncEx library.
However, if you need a named mutex, then you'll have to do something quite different. What that is depends on what exactly you're trying to do.
Update due to comments:
Since you're on the UI thread, there's no need to call into the dispatcher. You just need a SemaphoreSlim to keep them one-at-a-time:
private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
//Function that is attached to each pages "LayoutUpdated" call.
private async void AnyPageLayoutUpdated(object sender, object e)
{
await _mutex.WaitAsync();
try
{
LCDDriver.ILI9488.PaintScreen(sender);
}
finally
{
_mutex.Release();
}
}
Related
I have a legacy Windows Forms application that I am working on, I made some changes to the http client, I wanted to make it a singleton so that it could be reused throughout the application. It seems to be causing a deadlock.
I am going to paste all the code that I believe is involved below:
This is the calling code where the UI gets frozen, it never unfreezes.
private async void lbGroup_SelectedIndexChanged_1(object sender, EventArgs e)
{
int groupId = this.lbGroup.SelectedIndex + 1;
await LoadStores(groupId);
//The code below freezes the application
this.lbStore.DataSource = _stores;
this.txtSearch.Enabled = true;
this.lbStore.Enabled = true;
}
This is the LoadStores Method where the httpClient is used:
private async Task LoadStores(int group)
{
try
{
HttpResponseMessage res = await _httpClient.GetAsync("api/GetStoresByGroup/" + group.ToString());
res.EnsureSuccessStatusCode();
if (res.IsSuccessStatusCode)
{
var serializedStores = await res.Content.ReadAsStringAsync();
_stores = JsonConvert.DeserializeObject<IEnumerable<Store>>(serializedStores).Select(s => s.StoreName).ToList();
res.Content.Dispose();
}
}
catch (Exception ex)
{
ErrorLogger.LogError("Installation", $"Error getting stores list: {ex.Message}");
}
}
This is the Http Singleton Class:
public static class HttpClientSingleton
{
private static readonly HttpClient _instance;
static HttpClientSingleton()
{
_instance = new HttpClient();
_instance.BaseAddress = new Uri("https://www.i-city.co.za/");
_instance.DefaultRequestHeaders.Accept.Clear();
_instance.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
}
public static HttpClient Instance
{
get
{
return _instance;
}
}
}
This is the form constructor where the HttpClient gets initiliazed:
public partial class frmInstallationHelper : Form
{
private static string _configDir;
private static string _localConfigDir;
private static int _storeID;
private static Activation _activation;
private static HttpClient _httpClient = HttpClientSingleton.Instance;
private static IEnumerable<string> _stores;
private static IEnumerable<string> _franchisees;
private int _smsCounter;
If I wrap the http request in a using statement inside of the LoadStores method, the app runs fine, but I don't want to dispose of the http Client as that defeats the purpose of making it a singleton.
Update: Problem Found
After following #MongZhu's lead I replicated the program and confirmed that none of the above code was actually causing the deadlock. It was caused by another method that was triggered by the lbStore list Box onSelectChange event displayd below:
private void lbStore_SelectedIndexChanged_1(object sender, EventArgs e)
{
string store = this.lbStore.GetItemText(this.lbStore.SelectedItem);
LoadFranchisees(store).Wait();
this.lbFranchisees.DataSource = _franchisees;
}
The way I solved the problem was by changing it to look as follows:
private async void lbStore_SelectedIndexChanged_1(object sender, EventArgs e)
{
string store = this.lbStore.GetItemText(this.lbStore.SelectedItem);
await LoadFranchisees(store);
this.lbFranchisees.DataSource = _franchisees;
}
I was busy changing all the .wait() methods to async / await, and I must have forgotten this one.
The deadlock arises because you used Wait in a method which was triggered by an async opertaion. Unfortunately it was masked very good by the apparent hanging in the line of the initialization of the DataSource. But this initialization triggered the SelectedIndexChanged of the listbox which had the evil Wait call in it. Making this method async and await the result will evaporate the deadlock.
private async void lbStore_SelectedIndexChanged_1(object sender, EventArgs e)
{
string store = this.lbStore.GetItemText(this.lbStore.SelectedItem);
_franchisees = await LoadFranchisees(store);
this.lbFranchisees.DataSource = _franchisees;
}
I would suggest to return the stores directly from the method instead of using a class variable as transmitter. This way you would also avoid race conditions (to which methods that use class variables are very much prone) If you need it further you could store the returning value inside the _stores variable. But a loading method should rather return the results instead of secretely storing it somewhere hidden from the user of this method.
private async Task<List<Store>> LoadStores(int group)
{
try
{
HttpResponseMessage res = await _httpClient.GetAsync("api/GetStoresByGroup/" + group.ToString()))
res.EnsureSuccessStatusCode();
if (res.IsSuccessStatusCode)
{
var serializedStores = await res.Content.ReadAsStringAsync();
res.Content.Dispose();
return JsonConvert.DeserializeObject<IEnumerable<Store>>(serializedStores).Select(s => s.StoreName).ToList();
}
}
catch (Exception ex)
{
ErrorLogger.LogError("Installation", $"Error getting stores list: {ex.Message}");
}
}
You can await the result in the event:
private async void lbGroup_SelectedIndexChanged_1(object sender, EventArgs e)
{
int groupId = this.lbGroup.SelectedIndex + 1;
_stores = await LoadStores(groupId);
this.lbStore.DataSource = _stores;
this.txtSearch.Enabled = true;
this.lbStore.Enabled = true;
}
The same logic applies to the LoadFranchisees method, refactor it so that it returns the data. This makes your code much more understandable. Don't hide information from the reader of a method. It could be you in 6 Month trying to figure out what da heck you did there.... Be nice to your future self at least ;)
I want to start / stop a thread in order not to block the UI using button
public partial class Program_Form : Form
{
readonly BackgroundWorker m_oWorker;
[STAThread]
private void Program_Form_Load(object sender, EventArgs e)
{
// long code here
}
private async void DGW6BtnPrint_Click(object sender, EventArgs e)
{
Work.Printer_ Print = new Work.Printer_();
await Task.Run(() =>
{
Print.Print_File(this, dataGridView6, StatusText, progressBar1,
varriablesStatus);
});
}
public void BTN6PPauza_Click(object sender, EventArgs e)
{
//What i had tried
//_canceller.Dispose();
//_canceller.Cancel();
// varriablesStatus = false;
//thread2.break;
//autoResetEvent.WaitOne();
//thread2.Join();
//_manualResetEvent.Reset();
//thread2.Abort();
//_pauseEvent.Reset();
//varriablesStatus = "Pause";
//Print_Actions();
}
}
Referenced class:
namespace OfficeTools.Work
{
class Printer_
{
public void Print_File(Program_Form callForm, DataGridView DGW,
TextBox Status, ProgressBar Progress, bool varriablesStatus)
{
foreach (DataGridViewRow Row in DGW.Rows)
{
file = DGW.Rows[Row.Index].Cells[4].Value.ToString();
PrintFiles.Print_Word(file);
}
}
}
}
How can I start stop pause resume the thread because nothing worked from what I had tried, I think the problem is from the foreach loop
I never used threads, and I can not find an example similar with mine in order to understand how should I do.
What you are asking implies that you want to use the Thread.Suspend and Thread.Resume methods. Possibly like this:
private volatile Thread _printThread;
private async void DGW6BtnPrint_Click(object sender, EventArgs e)
{
Work.Printer_ Print = new Work.Printer_();
await Task.Run(() =>
{
_printThread = Thread.CurrentThread;
try
{
Print.Print_File(this, dataGridView6, StatusText, progressBar1,
varriablesStatus);
}
finally { _printThread = null; }
});
}
public void BTN6PPauza_Click(object sender, EventArgs e)
{
var printThread = _printThread;
if (printThread != null)
{
if (printThread.ThreadState.HasFlag(ThreadState.Running))
{
printThread.Suspend();
}
else if (printThread.ThreadState.HasFlag(ThreadState.Suspended))
{
printThread.Resume();
}
}
}
The documentation of these two methods includes several cautionary warnings that discourage usage:
Thread.Suspend has been deprecated. Use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources.
Do not use the Suspend and Resume methods to synchronize the activities of threads. You have no way of knowing what code a thread is executing when you suspend it. If you suspend a thread while it holds locks during a security permission evaluation, other threads in the AppDomain might be blocked. If you suspend a thread while it is executing a class constructor, other threads in the AppDomain that attempt to use that class are blocked. Deadlocks can occur very easily.
It's up to you if you want to accept these risks. If you ask me, you shouldn't.
Note: The Suspend and Resume methods are not supported on .NET Core and later platforms. On these platforms they throw a PlatformNotSupportedException exception. You can use them only if you target the .NET Framework platform.
i made this work, i do not know if it is the right way but for the moment it works
public partial class Program_Form : Form
{
readonly BackgroundWorker m_oWorker;
CancellationTokenSource _tokenSource = null;
[STAThread]
private void Program_Form_Load(object sender, EventArgs e)
{
// long code here
}
private async void DGW6BtnPrint_Click(object sender, EventArgs e)
{
_tokenSource = new CancellationTokenSource();
var token = _tokenSource.Token;
Work.Printer_ Print = new Work.Printer_();
await Task.Run(() =>
{
Print.Print_File(this, dataGridView6, StatusText, progressBar1, token);
});
}
public void BTN6PPauza_Click(object sender, EventArgs e)
{
_tokenSource.Cancel();
}
}
Referenced class:
namespace OfficeTools.Work
{
class Printer_
{
public void Print_File(Program_Form callForm, DataGridView DGW, TextBox Status, ProgressBar Progress, CancellationToken Token)
{
foreach (DataGridViewRow Row in DGW.Rows)
{
file = DGW.Rows[Row.Index].Cells[4].Value.ToString();
PrintFiles.Print_Word(file);
if (Token.IsCancellationRequested)
{
try
{
Winword.Quit(ref missing, ref missing, ref missing);
winword = null;
}
catch { }
return;
}
}
}
}
}
Kind regards all
Currently I am trying to create a background worker that can loop through some class functions, I created a class to store a few objects that are getting used globally (user settings and a few other things).
I essentially need to store the following line as an Action.
GV_Acc.load_page("weburl", 0);
Here is the majority of the code that I am using
Form Containing a Button:
private void btn_initialize_Click(object sender, EventArgs e){
CusWorker worker = new CusWorker();
worker.addwork(GV_Acc.load_page("weburl", 0));
worker.addwork(GV_Acc.json_populate(0));
worker.asyncworker.RunWorkerAsync();}
These are the 2 Classes I am using:
public class CusWorker
{
public BackgroundQueue asyncqueue { get;private set; }
private int tasks;
public System.ComponentModel.BackgroundWorker asyncworker = new System.ComponentModel.BackgroundWorker();
public CusWorker()
{
asyncqueue = new BackgroundQueue();
asyncworker.DoWork += new System.ComponentModel.DoWorkEventHandler(asyncworker_DoWork);
asyncworker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(asyncworker_RunWorkerCompleted);
}
public void addwork(Action action)
{
asyncqueue.QueueTask(action);
}
private void asyncworker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
}
private void asyncworker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
if (asyncqueue != null)
{
asyncworker.RunWorkerAsync();
}
}
}
public class BackgroundQueue
{
private Task previousTask = Task.FromResult(true);
private object key = new object();
public Task QueueTask(Action action)
{
lock (key)
{
previousTask = previousTask.ContinueWith(t => action()
, CancellationToken.None
, TaskContinuationOptions.None
, TaskScheduler.Default);
return previousTask;
}
}
public Task<T> QueueTask<T>(Func<T> work)
{
lock (key)
{
var task = previousTask.ContinueWith(t => work()
, CancellationToken.None
, TaskContinuationOptions.None
, TaskScheduler.Default);
previousTask = task;
return task;
}
}
}}
So Should I use "Actions" Or is there a better way to do what I am attempting?
PS:Honestly I don't have any idea what the above does at this point. All I know is that when I run my program and click the button, everything locks up for about 30 seconds. I'm trying to stop that from happening but I don't know where to start now. Am I using any of the above code correctly?
Edit: Found out that when Something is added to the background Queue it starts work immediately, So I don't need the background worker. I Will have to learn more about tasks.
I ended up using a work around method and getting rid of the BackgroundWorker.
Did not understand Tasks or Actions, now that I know more about the syntax, The background worker is completely useless. Correct Syntax
queue = new BackgroundQueue();
queue.queuetask(() => {code to run};);
I did not realize that the Method starts running the moment it is passed to QueueTask().
Feeling Pretty Stupid for this question
I have a service running some different tasks in a loop until the service is stopped.
However one of these tasks i calling a web service and this call can take several minutes to complete. I want to be able to stop the service instantly, 'cancelling' the web service call without calling Thread.Abort because that causes some strange behavior even if the only thing the thread is doing is calling this web service method.
How can i cancel or break from a synchronous method call (if it's even possible)?
Or should I try a different approach?
I have tried to use the AutoResetEvent and then calling Thread.Abort which is working fine in the below code sample, but when implementing this solution in the actual service I get some unexpected behavior probably because of what's going on in the external libraries I'm using.
AutoResetEvent and Thread.Abort:
class Program
{
static void Main(string[] args)
{
MainProgram p = new MainProgram();
p.Start();
var key = Console.ReadKey();
if (key.Key == ConsoleKey.Q)
p.Stop();
}
}
class MainProgram
{
private Thread workerThread;
private Thread webServiceCallerThread;
private volatile bool doWork;
public void Start()
{
workerThread = new Thread(() => DoWork());
doWork = true;
workerThread.Start();
}
public void Stop()
{
doWork = false;
webServiceCallerThread.Abort();
}
private void DoWork()
{
try
{
while (doWork)
{
AutoResetEvent are = new AutoResetEvent(false);
WebServiceCaller caller = new WebServiceCaller(are);
webServiceCallerThread = new Thread(() => caller.TimeConsumingMethod());
webServiceCallerThread.Start();
// Wait for the WebServiceCaller.TimeConsumingMethod to finish
WaitHandle.WaitAll(new[] { are });
// If doWork has been signalled to stop
if (!doWork)
break;
// All good - continue
Console.WriteLine(caller.Result);
}
}
catch (Exception e)
{
Console.Write(e);
}
}
}
class WebServiceCaller
{
private AutoResetEvent ev;
private int result;
public int Result
{
get { return result; }
}
public WebServiceCaller(AutoResetEvent ev)
{
this.ev = ev;
}
public void TimeConsumingMethod()
{
try
{
// Simulates a method running for 1 minute
Thread.Sleep(60000);
result = 1;
ev.Set();
}
catch (ThreadAbortException e)
{
ev.Set();
result = -1;
Console.WriteLine(e);
}
}
}
Can someone suggest a solution to this issue?
Try this
public void Start()
{
workerThread = new Thread(() => DoWork());
doWork = true;
workerThread.IsBackground = true;
workerThread.Start();
}
A thread is either a background thread or a foreground thread.
Background threads are identical to foreground threads, except that
background threads do not prevent a process from terminating. Once all
foreground threads belonging to a process have terminated, the common
language runtime ends the process. Any remaining background threads
are stopped and do not complete.
For more details see http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx
The solution is really this simple: Don't make calls that block for several minutes unless you want to block for several minutes. If there is no way to do a particular thing without blocking, potentially for several minutes, complain loudly to whoever wrote the code that imposes that painful requirement (or fix it yourself, if possible).
Once you've made the call, it's too late. You're committed. If the function you are calling doesn't provide a safe way to abort it, then there's no safe way.
As all you want to do is make one an asynchonrous web service call at a time and on each response make another call you can dispense with the worker thread and simply make an aynchronous call, register a callback and make another async call from the callback:
class Program
{
private static WebServiceCaller.TCMDelegate _wscDelegate;
private static readonly WebServiceCaller _wsCaller = new WebServiceCaller();
static void Main(string[] args)
{
_wscDelegate = _wsCaller.TimeConsumingMethod;
MakeWSCallAsync();
Console.WriteLine("Enter Q to quit");
while (Console.ReadLine().ToUpper().Trim()!="Q"){}
}
public static void MakeWSCallAsync()
{
_wscDelegate.BeginInvoke(OnWSCallComplete, null);
}
public static void OnWSCallComplete(IAsyncResult ar)
{
Console.WriteLine("Result {0}", _wscDelegate.EndInvoke(ar));
MakeWSCallAsync();
}
}
class WebServiceCaller
{
public delegate int TCMDelegate();
public int TimeConsumingMethod()
{
try
{
// Simulates a method running for 1 minute
Thread.Sleep(1000);
return 1;
}
catch (ThreadAbortException e)
{
return -1;
}
}
}
No blocking (well, the console thread is blocking on ReadLine()) and no windows kernal mode sync objects (AutoResetEvent) which are expensive.
I'm having a small background thread which runs for the applications lifetime - however when the application is shutdown, the thread should exit gracefully.
The problem is that the thread runs some code at an interval of 15 minutes - which means it sleeps ALOT.
Now in order to get it out of sleep, I toss an interrupt at it - my question is however, if there's a better approach to this, since interrupts generate ThreadInterruptedException.
Here's the gist of my code (somewhat pseudo):
public class BackgroundUpdater : IDisposable
{
private Thread myThread;
private const int intervalTime = 900000; // 15 minutes
public void Dispose()
{
myThread.Interrupt();
}
public void Start()
{
myThread = new Thread(ThreadedWork);
myThread.IsBackground = true; // To ensure against app waiting for thread to exit
myThread.Priority = ThreadPriority.BelowNormal;
myThread.Start();
}
private void ThreadedWork()
{
try
{
while (true)
{
Thread.Sleep(900000); // 15 minutes
DoWork();
}
}
catch (ThreadInterruptedException)
{
}
}
}
There's absolutely a better way - either use Monitor.Wait/Pulse instead of Sleep/Interrupt, or use an Auto/ManualResetEvent. (You'd probably want a ManualResetEvent in this case.)
Personally I'm a Wait/Pulse fan, probably due to it being like Java's wait()/notify() mechanism. However, there are definitely times where reset events are more useful.
Your code would look something like this:
private readonly object padlock = new object();
private volatile bool stopping = false;
public void Stop() // Could make this Dispose if you want
{
stopping = true;
lock (padlock)
{
Monitor.Pulse(padlock);
}
}
private void ThreadedWork()
{
while (!stopping)
{
DoWork();
lock (padlock)
{
Monitor.Wait(padlock, TimeSpan.FromMinutes(15));
}
}
}
For more details, see my threading tutorial, in particular the pages on deadlocks, waiting and pulsing, the page on wait handles. Joe Albahari also has a tutorial which covers the same topics and compares them.
I haven't looked in detail yet, but I wouldn't be surprised if Parallel Extensions also had some functionality to make this easier.
You could use an Event to Check if the Process should end like this:
var eventX = new AutoResetEvent(false);
while (true)
{
if(eventX.WaitOne(900000, false))
{
break;
}
DoWork();
}
There is CancellationTokenSource class in .NET 4 and later which simplifies this task a bit.
private readonly CancellationTokenSource cancellationTokenSource =
new CancellationTokenSource();
private void Run()
{
while (!cancellationTokenSource.IsCancellationRequested)
{
DoWork();
cancellationTokenSource.Token.WaitHandle.WaitOne(
TimeSpan.FromMinutes(15));
}
}
public void Stop()
{
cancellationTokenSource.Cancel();
}
Don't forget that CancellationTokenSource is disposable, so make sure you dispose it properly.
One method might be to add a cancel event or delegate that the thread will subscribe to. When the cancel event is invoke, the thread can stop itself.
I absolutely like Jon Skeets answer. However, this might be a bit easier to understand and should also work:
public class BackgroundTask : IDisposable
{
private readonly CancellationTokenSource cancellationTokenSource;
private bool stop;
public BackgroundTask()
{
this.cancellationTokenSource = new CancellationTokenSource();
this.stop = false;
}
public void Stop()
{
this.stop = true;
this.cancellationTokenSource.Cancel();
}
public void Dispose()
{
this.cancellationTokenSource.Dispose();
}
private void ThreadedWork(object state)
{
using (var syncHandle = new ManualResetEventSlim())
{
while (!this.stop)
{
syncHandle.Wait(TimeSpan.FromMinutes(15), this.cancellationTokenSource.Token);
if (!this.cancellationTokenSource.IsCancellationRequested)
{
// DoWork();
}
}
}
}
}
Or, including waiting for the background task to actually have stopped (in this case, Dispose must be invoked by other thread than the one the background thread is running on, and of course this is not perfect code, it requires the worker thread to actually have started):
using System;
using System.Threading;
public class BackgroundTask : IDisposable
{
private readonly ManualResetEventSlim threadedWorkEndSyncHandle;
private readonly CancellationTokenSource cancellationTokenSource;
private bool stop;
public BackgroundTask()
{
this.threadedWorkEndSyncHandle = new ManualResetEventSlim();
this.cancellationTokenSource = new CancellationTokenSource();
this.stop = false;
}
public void Dispose()
{
this.stop = true;
this.cancellationTokenSource.Cancel();
this.threadedWorkEndSyncHandle.Wait();
this.cancellationTokenSource.Dispose();
this.threadedWorkEndSyncHandle.Dispose();
}
private void ThreadedWork(object state)
{
try
{
using (var syncHandle = new ManualResetEventSlim())
{
while (!this.stop)
{
syncHandle.Wait(TimeSpan.FromMinutes(15), this.cancellationTokenSource.Token);
if (!this.cancellationTokenSource.IsCancellationRequested)
{
// DoWork();
}
}
}
}
finally
{
this.threadedWorkEndSyncHandle.Set();
}
}
}
If you see any flaws and disadvantages over Jon Skeets solution i'd like to hear them as i always enjoy learning ;-)
I guess this is slower and uses more memory and should thus not be used in a large scale and short timeframe. Any other?