How to access UI thread in C# - c#

I am trying to access the UI thread in C# for windows phone 8. So far I got this. However, once it runs SmartDispatcher, it jumps to finally with receipt == null.
I got the SmartDispatcher class from this website(http://www.jeff.wilcox.name/2010/04/propertychangedbase-crossthread/). I was wondering if other people had this problem and how to solve it.
private async void purchaseProduct()
{
try{
li = await Store.CurrentApp.LoadListingInformationAsync();
SmartDispatcher.BeginInvoke(async delegate()
{
receipt = await Store.CurrentApp.RequestProductPurchaseAsync(package_id, true);
});
}
catch
{
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR));
}
finally
{
if(receipt != null)
{
parseXML(package_id);
prepData();
httpPostData();
Store.CurrentApp.ReportProductFulfillment(package_id);
}
}
}

Of course it will jump there immediately, as you are commencing an asynchronous operation, which does not block, but returns immediately.
Look, if the object contains a method Invoke instead of BeginInvoke. Invoke will block until the operation is complete.
See this thread as a reference.

Related

Cross Thread invoke (c#, WaveEngine)

I'm looking for a way to invoke a function on a different thread.
We are working with a server(gRPC) which sends out data when it receives it, a task is running at the client and will proceed the loop once it receives new data(stream.MoveNext()).
Once it receives new data it will invoke a function, although this is done within a different thread
NOTE: I'm not getting the Cross-Thread Exception, this is because its disabled during build and testing on developer machine is impossible.
public static async Task ButtonStream()
{
var rpc = buttonClient.buttonPressed(new ButtonsSubscription());
try
{
using (rpc)
{
var stream = rpc.ResponseStream;
while (await stream.MoveNext())
{
if (stream.Current.Id >= persistantDic.Count)
{
int a = stream.Current.Id;
int b = persistantDic.Count;
//Console.WriteLine("{0} >= {1}", a,b);
throw new Exception("Something went wrong");
}
else
{
buttonPressed = stream.Current.Id;
gRPCEvents.ButtonUpdates?.Invoke ();
Console.WriteLine("Invoked from thread: "+Thread.CurrentThread.ManagedThreadId);
}
}
}
}
catch (RpcException e)
{
throw;
}
}
ButtonUpdates?.Invoke runs a function within main(threadID 1), When i press F1(Testing purpose only) i see that its running the function on Thread 1, but when it gets invoked its running function on Thread 4 (or 9, changes sometimes).
EDIT
The function on main thread is subscribed to the delegate invoked, which will be invoked by a task on thread 4
Resolved,
WaveEngine was so kind to provide me with an easy solution to hook in to their main thread
WaveServices.Dispatcher.RunOnWaveThread(() =>
{
//Any code here for execution
});

External Function Call Blocks UI thread

I am working on an application that talks to a motion controller over ethernet.
To connect to the controller I use a library provided by the supplier, to connect you create an instance of the controller than then tell it to connect, this has the chance to block for a few seconds (with no controllable timeout) if there is no controller present. This cause freeze ups in the UI.
To avoid this I thought I would be able to use Tasks to run the connection in a different thread.
ConnectionTask = Task.Factory.StartNew(() =>
{
try
{
RMCLink rmc = RMCLink.CreateEthernetLink(DeviceType.RMC70, "192.168.0.55");
RMC.Connect();
}
catch
{
this.logger.Log("Failed to connect");
}
}, TaskCreationOptions.LongRunning);
This has no effect whatsoever and the UI still locks up.
I think I am using them properly as if I replace it with the below code the UI is fine even though the separate thread takes a few seconds before the message comes out.
ConnectionTask = Task.Factory.StartNew(() =>
{
int x = 1;
while (x != 0) x++;
this.logger.Log("Failed to connect");
}, TaskCreationOptions.LongRunning);
Is there any way I can identify what is going on and prevent calls that I do not know anything about their inner workings from locking the UI thread.
Use async/await, something along the lines of:
public async void MyButton_Click(object sender, EventArgs e)
{
await CreateEthernetLink();
this.logger.Log("Connected!");
}
private async Task CreateEthernetLink()
{
var task = Task.Run(() => {
try
{
RMCLink rmc = RMCLink.CreateEthernetLink(DeviceType.RMC70, "192.168.0.55");
rmc.Connect();
}
catch
{
this.logger.Log("Failed to connect");
}});
await task;
}
The await will capture the current thread (or SynchronizationContext - in this case the UI thread which is being blocked) and restore it after the async work has been completed.
So the threading is all handled for you behind the scenes and you should notice no difference in your application other than the fact that your application no longer freezes when performing connections.
EDIT: I also noticed in your code your initializing rmc but calling connect on RMC. I don't think this is correct.

How to track if an async/awaitable task is running

I'm trying to transition from the Event-based Asynchronous Pattern where I tracked running methods using unique id's and the asynoperationmanager. As this has now been dropped from Windows 8 Apps I'm trying to get a similar effect with Async/Await but can't quite figure out how.
What I'm trying to achieve is something like
private async Task updateSomething()
{
if(***the method is already running***)
{
runagain = true;
}
else
{
await someMethod();
if (runagain)
{
run the method again
}
}
}
The part I'm struggling with is finding out if the method is running. I've tried creating a Task and looking at the status of both that and the .status of the async method but they don't appear to be the correct place to look.
Thanks
UPDATE: This is the current code I use in .net 4 to achieve the same result. _updateMetaDataAsync is a class based on the Event-Based Asynchronous Pattern.
private void updateMetaData()
{
if (_updateMetaDataAsync.IsTaskRunning(_updateMetaDataGuid_CheckAllFiles))
{
_updateMetaDataGuid_CheckAllFiles_Again = true;
}
else
{
_updateMetaDataGuid_CheckAllFiles_Again = false;
_updateMetaDataAsync.UpdateMetaDataAsync(_updateMetaDataGuid_CheckAllFiles);
}
}
private void updateMetaDataCompleted(object sender, UpdateMetaDataCompletedEventArgs e)
{
if (_updateMetaDataGuid_CheckAllFiles_Again)
{
updateMetaData();
}
}
async/await itself is intended to be used to create sequential operations executed asynchronously from the UI thread. You can get it to do parallel operations, but generally the operations "join" back to the UI thread with some sort of result. (there's also the possibility of doing "fire-and-forget" types of asynchronous operations with await but it's not recommended). i.e. there's nothing inherent to async/await to support progress reporting.
You can get progress out of code using async/await; but you need to use new progress interfaces like IProgress<T>. For more info on progress reporting with async/await, see http://blogs.msdn.com/b/dotnet/archive/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-apis.aspx. Migrating to this should just be a matter of calling an IProgress delegate instead of a Progress event.
If you're using a Task you've created, you can check the Task's Status property (or just see Task.IsCompleted if completion is the only state you are interested in).
That being said, await will not "return" until the operation either completes, raises an exception, or cancels. You can basically safely assume that, if you're still waiting on the "await", your task hasn't completed.
SemaphoreSlim queueToAccessQueue = new SemaphoreSlim(1);
object queueLock = new object();
long queuedRequests = 0;
Task _loadingTask;
public void RetrieveItems() {
lock (queueLock) {
queuedRequests++;
if (queuedRequests == 1) { // 1 is the minimum size of the queue before another instance is queued
_loadingTask = _loadingTask?.ContinueWith(async () => {
RunTheMethodAgain();
await queueToAccessQueue.WaitAsync();
queuedRequests = 0; // indicates that the queue has been cleared;
queueToAccessQueue.Release()
}) ?? Task.Run(async () => {
RunTheMethodAgain();
await queueToAccessQueue.WaitAsync();
queuedRequests = 0; // indicates that the queue has been cleared;
queueToAccessQueue.Release();
});
}
}
}
public void RunTheMethodAgain() {
** run the method again **
}
The added bonus is that you can see how many items are sitting in the queue!

Object synchronization method was called from an unsynchronized block of code. Exception on Mutex.Release()

I have found different articles about this exception but none of them was my case.
Here is the source code:
class Program
{
private static Mutex mutex;
private static bool mutexIsLocked = false;
static void Main(string[] args)
{
ICrmService crmService =
new ArmenianSoftware.Crm.Common.CrmServiceWrapper(GetCrmService("Armsoft", "crmserver"));
//Lock mutex for concurrent access to workflow
mutex = new Mutex(true, "ArmenianSoftware.Crm.Common.FilterCtiCallLogActivity");
mutexIsLocked = true;
//Create object for updating filtered cti call log
ArmenianSoftware.Crm.Common.FilterCtiCallLog filterCtiCallLog =
new ArmenianSoftware.Crm.Common.FilterCtiCallLog(crmService);
//Bind events
filterCtiCallLog.CtiCallsRetrieved += new EventHandler<ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs>(filterCtiCallLog_CtiCallsRetrieved);
//Execute filter
try
{
filterCtiCallLog.CreateFilteredCtiCallLogSync();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (mutexIsLocked)
{
mutexIsLocked = false;
mutex.ReleaseMutex();
}
}
}
static void filterCtiCallLog_CtiCallsRetrieved(object sender,
ArmenianSoftware.Crm.Common.CtiCallsRetrievedEventArgs e)
{
tryasasas
{
if (mutexIsLocked)
{
mutexIsLocked = false;
mutex.ReleaseMutex();
}
}
catch (Exception ex)
{
throw ex;
}
}
}
filterCtiCallLog.CreateFilteredCtiCallLogSync(); function executes requests to server, and raises some events, one of which is CtiCallsRetrieve event. And I need to release the mutex when this event is fired. But on calling the mutex.Release() function exception is thrown. CreateFilteredCtiCallLogSync works synchronously. What is the problem?
Keeping a bool around that indicates that the mutex is owned is a grave mistake. You are not making the bool thread-safe. You got into this pickle because you are using the wrong synchronization object. A mutex has thread-affinity, the owner of a mutex is a thread. The thread that acquired it must also be the one that calls ReleaseMutex(). Which is why your code bombs.
You in all likelihood need an event here, use AutoResetEvent. Create it in the main thread, call Set() in the worker, WaitOne() in the main thread to wait for the worker to complete its job. And dispose it afterwards. Also note that using a thread to perform a job and having your main thread wait for its completion is not productive. You might as well have the main thread do the job.
If you are actually doing this to protect access to an object that's not thread-safe (it isn't clear) then use the lock statement.
Another reason why this exception may occur:
if (Monitor.TryEnter(_lock))
{
try
{
... await MyMethodAsync(); ...
}
finally
{
Monitor.Exit(_lock);
}
}
I get this exception on Monitor.Exit when after 'await' another thread continues execution.
Edit:
Use SemaphoreSlim, because it doesn't require releasing thread to be the same.
You will also run into this exception if you do the following:
mutex.WaitOne();
… Some Work...
await someTask;
mutex.ReleaseMutex();
That's because the code after the await can be executed on a different thread from the line just before. Basically, it seems that if you asynch code now (in early 2020), Mutexes simply don't work. Use events or something.
I have found the problem. First several things about the filterCtiCallLog class. I have designed it so to work both asynchronous and synchronous. For first I have written code for asynchronous execution. I needed a way to trigger events from child worker thread to parent, to report the working state. For this I have used AsyncOperation class and it's post method. Here is the code part for triggering CtiCallsRetrieved event.
public class FilterCtiCallLog
{
private int RequestCount = 0;
private AsyncOperation createCallsAsync = null;
private SendOrPostCallback ctiCallsRetrievedPost;
public void CreateFilteredCtiCallLogSync()
{
createCallsAsync = AsyncOperationManager.CreateOperation(null);
ctiCallsRetrievedPost = new SendOrPostCallback(CtiCallsRetrievedPost);
CreateFilteredCtiCallLog();
}
private void CreateFilteredCtiCallLog()
{
int count=0;
//do the job
//............
//...........
//Raise the event
createCallsAsync.Post(CtiCallsRetrievedPost, new CtiCallsRetrievedEventArgs(count));
//...........
//...........
}
public event EventHandler<CtiCallsRetrievedEventArgs> CtiCallsRetrieved;
private void CtiCallsRetrievedPost(object state)
{
CtiCallsRetrievedEventArgs args = state as CtiCallsRetrievedEventArgs;
if (CtiCallsRetrieved != null)
CtiCallsRetrieved(this, args);
}
}
As you can see the code is executing synchronously. The problem here is in AsyncOperation.Post() method. I presumed that if it is called in the main thread it will act as simply triggering the event, not posting it to parent thread. However it wasn't the case. I don't know how it is working, but I have changed the code, to check if the CreateFilteredCtiCallLog is called sync or async. And if it is async call I used AsyncOperation.Post method, if not, I have simply triggered the EventHandler if it is not null. Here is the corrected code
public class FilterCtiCallLog
{
private int RequestCount = 0;
private AsyncOperation createCallsAsync = null;
private SendOrPostCallback ctiCallsRetrievedPost;
public void CreateFilteredCtiCallLogSync()
{
createCallsAsync = AsyncOperationManager.CreateOperation(null);
ctiCallsRetrievedPost = new SendOrPostCallback(CtiCallsRetrievedPost);
CreateFilteredCtiCallLog(false);
}
private void CreateFilteredCtiCallLog(bool isAsync)
{
int count=0;
//do the job
//............
//...........
//Raise the event
RaiseEvent(CtiCallsRetrievedPost, new CtiCallsRetrievedEventArgs(count),isAsync);
//...........
//...........
}
public event EventHandler<CtiCallsRetrievedEventArgs> CtiCallsRetrieved;
private void RaiseEvent(SendOrPostCallback callback, object state, bool isAsync)
{
if (isAsync)
createCallsAsync.Post(callback, state);
else
callback(state);
}
private void CtiCallsRetrievedPost(object state)
{
CtiCallsRetrievedEventArgs args = state as CtiCallsRetrievedEventArgs;
if (CtiCallsRetrieved != null)
CtiCallsRetrieved(this, args);
}
}
Thanks everybody for the answers!
I have seen this happen when you lock code using a Monitor, then call an async code and you get this, when using a lock(object) you get a compiler error, however between monitor.enter(object) and Monitor.Exist(object) the compiler does not complain... unfortunately.
Using a flag to attempt to monitor a kernel synchro object state will just not work - the point of using those synchro calls is that they work correctly without any explicit checking. Setting flags will just cause intermittent problems because the flag may be changed inappropriately due to interrupts between checking the flag and acting on it.
A mutex can only be released by the threat that acquired it. If you callback is called by a different thread, (one internal to CreateFilteredCtiCallLogSync() or a kernel thread pool), the release will fail.
It's not clear exactly what you are attempting to do. Presumably, you want to serialize access to CreateFilteredCtiCallLogSync() and the callback flags that the instance is available for re-use? If so, you could use a semaphore instead - init. it to one unit, wait for it at the start and release it in the callback.
Is there some issue where sometimes the callback is not called, and hence the try/finally/release? If so this way out seems a bit dodgy if the callback is asychronous and may be called by another thread after the setup thread has left the function.
I only had this one once or twice, and in every case it came about by trying to release a mutex I didn't own.
Are you sure the events are raised on the same thread the mutex was acquired on?
Although you mention that filterCtiCallLog.CreateFilteredCtiCallLogSync() is a blocking call, perhaps it spawns of worker threads that raise the event?
Maybe not the most meaningful error message, I've seen this happen in some third party code as below,
object obj = new object();
lock (obj)
{
//do something
Monitor.Exit(obj);//obj released
}//exception happens here, when trying to release obj
I have read the thread and got some ideas. But did not know what exactly need to do to solve the issue. I face the same error when uploading the image to the s3 at nopCommerce solution.And the below code is working for me.
using var mutex = new Mutex(false, thumbFileName);
mutex.WaitOne();
try
{
if (pictureBinary != null)
{
try
{
using var image = SKBitmap.Decode(pictureBinary);
var format = GetImageFormatByMimeType(picture.MimeType);
pictureBinary = ImageResize(image, format, targetSize);
}
catch
{
}
}
if (s3Enabled)
//await S3UploadImageOnThumbsAsync(thumbFileName, pictureBinary, picture.MimeType, picture, targetSize);
// The above code was causing the issue. Because it is wait for the thread.
//So I replace the code below line and the error disappear. This also kind of same implementation by nopCommerce.
//The thread need to wait.
S3UploadImageOnThumbsAsync(thumbFileName, pictureBinary, picture.MimeType, picture, targetSize).Wait();
else
File.WriteAllBytes(thumbFilePath, pictureBinary);
}
finally
{
mutex.ReleaseMutex();
}

Can I write a C# method that will terminate execution of anyone who calls it (within the same class)?

I have a C# class that is typically executed in a thread. The caller can call a .Cancel method to stop the execution of the thread.
The ".Cancel" method will set a boolean "Cancelled" property to "True". The actual cancellation comes from little blocks like this, scattered all over the place in my code:
public void ThisGetsExecutedAsAThread()
{
.....
DoThing1;
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
return;
}
DoThing2;
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
return;
}
DoThing3;
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
return;
}
.....
}
This approach works quite well (i.e., the caller can cancel the action, and the execution stops within a few seconds), but as you can see it is quite repetitive.
I'd like to replace those blocks with something more like this:
...Do some action...
TerminateIfCancelled;
...Do some action....
Is it possible to define a "TerminateIfCancelled" that will cause the caller to return?
Or have I missed some much better general solution to this problem..?
Best way to end a thread is return from its function, and there are only 2 ways of returning from a function - return and throw, so if you don't like if(Cancelled) return; you can define new exception type (CancelledException for example) and throw it in your TerminateIfCancelled:
sealed class CancelledException : Exception { }
private void TerminateIfCancelled()
{
if (Cancelled)
{
LogMsg = "Cancelled!";
Finished = true;
throw new CancelledException();
}
}
public void ThisGetsExecutedAsAThread()
{
try
{
DoThing1;
TerminateIfCancelled();
DoThing2;
TerminateIfCancelled();
DoThing3;
TerminateIfCancelled();
}
catch(CancelledException)
{
return;
}
}
C# will help you with cancel/error/continue actions if you use Task or Task<T>
Get the thread instance that you created and abort it from another thread:
Thread oThread = new Thread(new ThreadStart(someDelegate));
oThread.Start()
and on your "CancelButton_Click":
oThread.Abort()
It will raise a ThreadAbortedException on the Thread. You should catch that exception and fail gracefully.

Categories