How to fix resource leak because of missing EndInvoke call? - c#

I would like to use this solution to call Console.ReadLine() with a timeout:
delegate string ReadLineDelegate();
string ReadLine(int timeoutms)
{
string resultstr = null;
ReadLineDelegate d = Console.ReadLine;
IAsyncResult result = d.BeginInvoke(null, null);
result.AsyncWaitHandle.WaitOne(timeoutms);//timeout e.g. 15000 for 15 secs
if (result.IsCompleted)
{
resultstr = d.EndInvoke(result);
Console.WriteLine("Read: " + resultstr);
}
else
{
Console.WriteLine("Timed out!");
// Bug? resource leak? No d.EndInvoke(), which blocks until Console.ReadLine() returns
}
result.AsyncWaitHandle.Close();
return resultstr;
}
but commenters warned:
every ReadLine you call sits there waiting for input.
If you call it 100 times, it creates 100 threads
which don't all go away until you hit Enter 100 times!
...especially because I want to call this repeatedly in a forever-loop.
I understand that every BeginInvoke() needs a EndInvoke() but I don't want a blocking EndInvoke call in the else branch. Somehow we need to abort the running Console.ReadLine() call rather than let it run to completion, because it may never complete.
So all this (complex) code helped me to get Console.ReadLine to return at a timeout, but does not end the Console.ReadLine to quit or otherwise go away.
How can we make this to work correctly, without running into resource leaks?
NB: I added the AsyncWaitHandle.Close() as advised by MS Calling Sync calls asynchronously

After reading a lot of comments on several similar questions, as mentioned, I come to believe there is no real solution here. The Microsoft way with Begin/EndInvoke is
rather complex, and:
not adequate
A more straightforward method is to run the synchronous call in another thread, use a timing method to keep track of the timeout, and use Thread.Abort() to get rid of the timed-out synchronous call.
Caveat:
The synchronous call may or may not support to be aborted. For example, Console.ReadLine() will be aborted OK, but if you restart the thread, no data will be read from the Console anymore.
The accepted solution on the original question on top of my posting above uses a second thread, and a timing method. However, it does not kill the sychronous call but keeps it running because it is needed for subsequent async calls, which is a fine hack.
The code for using a second thread is actually straighforward:
public class MySyncProc
{
/// <summary>
/// Value returned from the process after completion
/// </summary>
public string Result = null;
...other shared data...
public MySyncProc() { }
public void Run()
{
Result = LengthyProcess(...);
return;
}
}
public string Run(int TimeoutMs)
{
MySyncProc SyncP = new MySyncProc() { arg1 = ..., etc };
//
Thread T = new Thread(SyncP.Run);
T.Start();
//
DateTime StopTime = DateTime.Now.AddMilliseconds(TimeoutMs);
while (DateTime.Now < StopTime && SyncP.Result == null)
{
Thread.Sleep(200);
}
if (T.IsAlive)
{
T.Abort();
Console.WriteLine("Aborted thread for: {0}", Name);
}
return SyncP.Result;
}
If you don't like the polling, use the slightly more complex AutoResetEvent as in the mentioned accepted solution.

Related

Interrupt method execution on demand

I do have a method for which the execution time might take a while (approx. 2 minutes) running inside a task:
public Task BaseWorkerTask { get; set; }
public void Initialize()
{
BaseWorkerTask = Task.Run(() =>
{
BaseWorker();
});
}
public void BaseWorker()
{
Server.Speak(Packet.Greeting);
while (WaitServerResponse())
{
DoSomethingElse();
}
var response = Server.GetResponse();
if (response.Equals("abc"))
{
DoAbcTask();
}
else if (response.Equals("def"))
{
[...]
}
[...]
}
I would like to be able to interrupt it's execution for a given period of time in order to do some other server calls. What is important to note here, is that I want it to "pause" script execution at current line in the BaseWorker method, just where it's exactly at.
Something like:
if (!BaseWorkerTask.IsCompleted)
{
// Pause to do something else
// BaseWorkerTask.StopAtCurrentPlace();
DoSomethingElse();
// Once something else is done, resume BaseWorkerTask
// BaseWorkerTask.Resume();
}
Can such approach be achieved?
I have been trying to play with blocking a thread, however I was only able to block it once the method has finished using endless loop with System.Threading.Thread.Sleep(...).
Thread.Suspend is probably the closest you'll get, but it's marked as obsolete with the following (relevant) warning:
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.
In short, anything that can do this would be a bad idea for exactly the same reasons as above.
Attempting to use it on thread-pool threads virtually assures you of malfunction.
If you want to do this, you'll have to think of a way that the task can co-operate in its own pausing. Likely, this will involve peppering the code with synchronization stuff.
What's taking so long anyway?
I would use some kind of a bool flag, similar to a cancellation token. Set it to true when you want to suspend execution of the task, and inside of the BaseWorker check the value of the variable at various places. If it's true, use Thread.Sleep to halt execution until it's set to false.
Example:
bool suspendExecution = false;
public void Initialize()
{
BaseWorkerTask = Task.Run(() =>
{
BaseWorker(ref suspendExecution);
});
}
public void BaseWorker(ref bool suspend)
{
while (WaitServerResponse())
{
if (suspend)
{
while (suspend)
{
Thread.Sleep(1000);
}
}
DoSomethingElse();
}
}

How to cancel a task, after timeout? [duplicate]

We could abort a Thread like this:
Thread thread = new Thread(SomeMethod);
.
.
.
thread.Abort();
But can I abort a Task (in .Net 4.0) in the same way not by cancellation mechanism. I want to kill the Task immediately.
The guidance on not using a thread abort is controversial. I think there is still a place for it but in exceptional circumstance. However you should always attempt to design around it and see it as a last resort.
Example;
You have a simple windows form application that connects to a blocking synchronous web service. Within which it executes a function on the web service within a Parallel loop.
CancellationTokenSource cts = new CancellationTokenSource();
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
Parallel.ForEach(iListOfItems, po, (item, loopState) =>
{
Thread.Sleep(120000); // pretend web service call
});
Say in this example, the blocking call takes 2 mins to complete. Now I set my MaxDegreeOfParallelism to say ProcessorCount. iListOfItems has 1000 items within it to process.
The user clicks the process button and the loop commences, we have 'up-to' 20 threads executing against 1000 items in the iListOfItems collection. Each iteration executes on its own thread. Each thread will utilise a foreground thread when created by Parallel.ForEach. This means regardless of the main application shutdown, the app domain will be kept alive until all threads have finished.
However the user needs to close the application for some reason, say they close the form.
These 20 threads will continue to execute until all 1000 items are processed. This is not ideal in this scenario, as the application will not exit as the user expects and will continue to run behind the scenes, as can be seen by taking a look in task manger.
Say the user tries to rebuild the app again (VS 2010), it reports the exe is locked, then they would have to go into task manager to kill it or just wait until all 1000 items are processed.
I would not blame you for saying, but of course! I should be cancelling these threads using the CancellationTokenSource object and calling Cancel ... but there are some problems with this as of .net 4.0. Firstly this is still never going to result in a thread abort which would offer up an abort exception followed by thread termination, so the app domain will instead need to wait for the threads to finish normally, and this means waiting for the last blocking call, which would be the very last running iteration (thread) that ultimately gets to call po.CancellationToken.ThrowIfCancellationRequested.
In the example this would mean the app domain could still stay alive for up to 2 mins, even though the form has been closed and cancel called.
Note that Calling Cancel on CancellationTokenSource does not throw an exception on the processing thread(s), which would indeed act to interrupt the blocking call similar to a thread abort and stop the execution. An exception is cached ready for when all the other threads (concurrent iterations) eventually finish and return, the exception is thrown in the initiating thread (where the loop is declared).
I chose not to use the Cancel option on a CancellationTokenSource object. This is wasteful and arguably violates the well known anti-patten of controlling the flow of the code by Exceptions.
Instead, it is arguably 'better' to implement a simple thread safe property i.e. Bool stopExecuting. Then within the loop, check the value of stopExecuting and if the value is set to true by the external influence, we can take an alternate path to close down gracefully. Since we should not call cancel, this precludes checking CancellationTokenSource.IsCancellationRequested which would otherwise be another option.
Something like the following if condition would be appropriate within the loop;
if (loopState.ShouldExitCurrentIteration || loopState.IsExceptional || stopExecuting) {loopState.Stop(); return;}
The iteration will now exit in a 'controlled' manner as well as terminating further iterations, but as I said, this does little for our issue of having to wait on the long running and blocking call(s) that are made within each iteration (parallel loop thread), since these have to complete before each thread can get to the option of checking if it should stop.
In summary, as the user closes the form, the 20 threads will be signaled to stop via stopExecuting, but they will only stop when they have finished executing their long running function call.
We can't do anything about the fact that the application domain will always stay alive and only be released when all foreground threads have completed. And this means there will be a delay associated with waiting for any blocking calls made within the loop to complete.
Only a true thread abort can interrupt the blocking call, and you must mitigate leaving the system in a unstable/undefined state the best you can in the aborted thread's exception handler which goes without question. Whether that's appropriate is a matter for the programmer to decide, based on what resource handles they chose to maintain and how easy it is to close them in a thread's finally block. You could register with a token to terminate on cancel as a semi workaround i.e.
CancellationTokenSource cts = new CancellationTokenSource();
ParallelOptions po = new ParallelOptions();
po.CancellationToken = cts.Token;
po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
Parallel.ForEach(iListOfItems, po, (item, loopState) =>
{
using (cts.Token.Register(Thread.CurrentThread.Abort))
{
Try
{
Thread.Sleep(120000); // pretend web service call
}
Catch(ThreadAbortException ex)
{
// log etc.
}
Finally
{
// clean up here
}
}
});
but this will still result in an exception in the declaring thread.
All things considered, interrupt blocking calls using the parallel.loop constructs could have been a method on the options, avoiding the use of more obscure parts of the library. But why there is no option to cancel and avoid throwing an exception in the declaring method strikes me as a possible oversight.
But can I abort a Task (in .Net 4.0) in the same way not by
cancellation mechanism. I want to kill the Task immediately.
Other answerers have told you not to do it. But yes, you can do it. You can supply Thread.Abort() as the delegate to be called by the Task's cancellation mechanism. Here is how you could configure this:
class HardAborter
{
public bool WasAborted { get; private set; }
private CancellationTokenSource Canceller { get; set; }
private Task<object> Worker { get; set; }
public void Start(Func<object> DoFunc)
{
WasAborted = false;
// start a task with a means to do a hard abort (unsafe!)
Canceller = new CancellationTokenSource();
Worker = Task.Factory.StartNew(() =>
{
try
{
// specify this thread's Abort() as the cancel delegate
using (Canceller.Token.Register(Thread.CurrentThread.Abort))
{
return DoFunc();
}
}
catch (ThreadAbortException)
{
WasAborted = true;
return false;
}
}, Canceller.Token);
}
public void Abort()
{
Canceller.Cancel();
}
}
disclaimer: don't do this.
Here is an example of what not to do:
var doNotDoThis = new HardAborter();
// start a thread writing to the console
doNotDoThis.Start(() =>
{
while (true)
{
Thread.Sleep(100);
Console.Write(".");
}
return null;
});
// wait a second to see some output and show the WasAborted value as false
Thread.Sleep(1000);
Console.WriteLine("WasAborted: " + doNotDoThis.WasAborted);
// wait another second, abort, and print the time
Thread.Sleep(1000);
doNotDoThis.Abort();
Console.WriteLine("Abort triggered at " + DateTime.Now);
// wait until the abort finishes and print the time
while (!doNotDoThis.WasAborted) { Thread.CurrentThread.Join(0); }
Console.WriteLine("WasAborted: " + doNotDoThis.WasAborted + " at " + DateTime.Now);
Console.ReadKey();
You shouldn't use Thread.Abort()
Tasks can be Cancelled but not aborted.
The Thread.Abort() method is (severely) deprecated.
Both Threads and Tasks should cooperate when being stopped, otherwise you run the risk of leaving the system in a unstable/undefined state.
If you do need to run a Process and kill it from the outside, the only safe option is to run it in a separate AppDomain.
This answer is about .net 3.5 and earlier.
Thread-abort handling has been improved since then, a.o. by changing the way finally blocks work.
But Thread.Abort is still a suspect solution that you should always try to avoid.
And in .net Core (.net 5+) Thread.Abort() will now throw a PlatformNotSupportedException .
Kind of underscoring the 'deprecated' point.
Everyone knows (hopefully) its bad to terminate thread. The problem is when you don't own a piece of code you're calling. If this code is running in some do/while infinite loop , itself calling some native functions, etc. you're basically stuck. When this happens in your own code termination, stop or Dispose call, it's kinda ok to start shooting the bad guys (so you don't become a bad guy yourself).
So, for what it's worth, I've written those two blocking functions that use their own native thread, not a thread from the pool or some thread created by the CLR. They will stop the thread if a timeout occurs:
// returns true if the call went to completion successfully, false otherwise
public static bool RunWithAbort(this Action action, int milliseconds) => RunWithAbort(action, new TimeSpan(0, 0, 0, 0, milliseconds));
public static bool RunWithAbort(this Action action, TimeSpan delay)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
var source = new CancellationTokenSource(delay);
var success = false;
var handle = IntPtr.Zero;
var fn = new Action(() =>
{
using (source.Token.Register(() => TerminateThread(handle, 0)))
{
action();
success = true;
}
});
handle = CreateThread(IntPtr.Zero, IntPtr.Zero, fn, IntPtr.Zero, 0, out var id);
WaitForSingleObject(handle, 100 + (int)delay.TotalMilliseconds);
CloseHandle(handle);
return success;
}
// returns what's the function should return if the call went to completion successfully, default(T) otherwise
public static T RunWithAbort<T>(this Func<T> func, int milliseconds) => RunWithAbort(func, new TimeSpan(0, 0, 0, 0, milliseconds));
public static T RunWithAbort<T>(this Func<T> func, TimeSpan delay)
{
if (func == null)
throw new ArgumentNullException(nameof(func));
var source = new CancellationTokenSource(delay);
var item = default(T);
var handle = IntPtr.Zero;
var fn = new Action(() =>
{
using (source.Token.Register(() => TerminateThread(handle, 0)))
{
item = func();
}
});
handle = CreateThread(IntPtr.Zero, IntPtr.Zero, fn, IntPtr.Zero, 0, out var id);
WaitForSingleObject(handle, 100 + (int)delay.TotalMilliseconds);
CloseHandle(handle);
return item;
}
[DllImport("kernel32")]
private static extern bool TerminateThread(IntPtr hThread, int dwExitCode);
[DllImport("kernel32")]
private static extern IntPtr CreateThread(IntPtr lpThreadAttributes, IntPtr dwStackSize, Delegate lpStartAddress, IntPtr lpParameter, int dwCreationFlags, out int lpThreadId);
[DllImport("kernel32")]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32")]
private static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
While it's possible to abort a thread, in practice it's almost always a very bad idea to do so. Aborthing a thread means the thread is not given a chance to clean up after itself, leaving resources undeleted, and things in unknown states.
In practice, if you abort a thread, you should only do so in conjunction with killing the process. Sadly, all too many people think ThreadAbort is a viable way of stopping something and continuing on, it's not.
Since Tasks run as threads, you can call ThreadAbort on them, but as with generic threads you almost never want to do this, except as a last resort.
I faced a similar problem with Excel's Application.Workbooks.
If the application is busy, the method hangs eternally. My approach was simply to try to get it in a task and wait, if it takes too long, I just leave the task be and go away (there is no harm "in this case", Excel will unfreeze the moment the user finishes whatever is busy).
In this case, it's impossible to use a cancellation token. The advantage is that I don't need excessive code, aborting threads, etc.
public static List<Workbook> GetAllOpenWorkbooks()
{
//gets all open Excel applications
List<Application> applications = GetAllOpenApplications();
//this is what we want to get from the third party library that may freeze
List<Workbook> books = null;
//as Excel may freeze here due to being busy, we try to get the workbooks asynchronously
Task task = Task.Run(() =>
{
try
{
books = applications
.SelectMany(app => app.Workbooks.OfType<Workbook>()).ToList();
}
catch { }
});
//wait for task completion
task.Wait(5000);
return books; //handle outside if books is null
}
This is my implementation of an idea presented by #Simon-Mourier, using the dotnet thread, short and simple code:
public static bool RunWithAbort(this Action action, int milliseconds)
{
if (action == null) throw new ArgumentNullException(nameof(action));
var success = false;
var thread = new Thread(() =>
{
action();
success = true;
});
thread.IsBackground = true;
thread.Start();
thread.Join(milliseconds);
thread.Abort();
return success;
}
You can "abort" a task by running it on a thread you control and aborting that thread. This causes the task to complete in a faulted state with a ThreadAbortException. You can control thread creation with a custom task scheduler, as described in this answer. Note that the caveat about aborting a thread applies.
(If you don't ensure the task is created on its own thread, aborting it would abort either a thread-pool thread or the thread initiating the task, neither of which you typically want to do.)
using System;
using System.Threading;
using System.Threading.Tasks;
...
var cts = new CancellationTokenSource();
var task = Task.Run(() => { while (true) { } });
Parallel.Invoke(() =>
{
task.Wait(cts.Token);
}, () =>
{
Thread.Sleep(1000);
cts.Cancel();
});
This is a simple snippet to abort a never-ending task with CancellationTokenSource.

Call a method and cancel it and return to the calling method if it takes too long

Is there a way in c# to call a method so that if the method takes to long to complete, the method will be canceled and it will return to the calling method? I think I can do this with threading but what if threading is not needed?
For reference, the method I may need to kill/stop/abort is calling the CorelDraw 15 API. This opens an instance of CorelDraw and I have received non-repeatable errors in this method. Meaning, I can process the same image twice and one time it will freeze or error and the other it will not.
The current solution to the issue I am using is to have a second application that does Process.Start(firstAppExecutablePath) and then checks a variable in a text file and if the variable doesn't change after 10 minutes, .Kill(); is called on the instance of the process. I would prefer to avoid this solution if possible as it seems clunky and prone to issues. Since it runs .Kill(); it is being very messy in how things close but generally does not cause an issue.
Not built-in, no, since interrupting arbitrary code cannot be done safely (what if it's in the middle of calling a C library function (that doesn't support exceptions) which has just taken a global lock and needs to release it?).
But you can write such support yourself. I wouldn't add threads to the mix unless absolutely necessary, since they come with an entire new dimension of potential problems.
Example:
void Caller()
{
int result;
if (TryDoSomething(out result, 100)) {
System.Console.WriteLine("Result: {0}", result);
}
}
bool TryDoSomething(out int result, int timeoutMillis)
{
var sw = Stopwatch.StartNew();
result = 0x12345678;
for (int i = 0; i != 100000000; ++i) {
if (sw.ElapsedMilliseconds > timeoutMillis)
return false;
result += i / (result % 43) + (i % 19);
}
return true;
}
Threading is absolutely needed unless you are ok with checking the timeout from within the function - which probably you arn't. So here is a minimalistic approach with threads:
private static bool ExecuteWithTimeout(TimeSpan timeout, Action action)
{
Thread x = new Thread(() => { action(); });
x.Start();
if (!x.Join(timeout))
{
x.Abort(); //Or Interrupt instead, if you use e.g. Thread.Sleep in your method
return false;
}
return true;
}

Use a Task to avoid multiple calls to expensive operation and to cache its result

I have an async method that fetches some data from a database. This operation is fairly expensive, and takes a long time to complete. As a result, I'd like to cache the method's return value. However, it's possible that the async method will be called multiple times before its initial execution has a chance to return and save its result to the cache, resulting in multiple calls to this expensive operation.
To avoid this, I'm currently reusing a Task, like so:
public class DataAccess
{
private Task<MyData> _getDataTask;
public async Task<MyData> GetDataAsync()
{
if (_getDataTask == null)
{
_getDataTask = Task.Run(() => synchronousDataAccessMethod());
}
return await _getDataTask;
}
}
My thought is that the initial call to GetDataAsync will kick off the synchronousDataAccessMethod method in a Task, and any subsequent calls to this method before the Task has completed will simply await the already running Task, automatically avoiding calling synchronousDataAccessMethod more than once. Calls made to GetDataAsync after the private Task has completed will cause the Task to be awaited, which will immediately return the data from its initial execution.
This seems to be working, but I'm having some strange performance issues that I suspect may be tied to this approach. Specifically, awaiting _getDataTask after it has completed takes several seconds (and locks the UI thread), even though the synchronousDataAccessMethod call is not called.
Am I misusing async/await? Is there a hidden gotcha that I'm not seeing? Is there a better way to accomplish the desired behavior?
EDIT
Here's how I call this method:
var result = (await myDataAccessObject.GetDataAsync()).ToList();
Maybe it has something to do with the fact that the result is not immediately enumerated?
If you want to await it further up the call stack, I think you want this:
public class DataAccess
{
private Task<MyData> _getDataTask;
private readonly object lockObj = new Object();
public async Task<MyData> GetDataAsync()
{
lock(lockObj)
{
if (_getDataTask == null)
{
_getDataTask = Task.Run(() => synchronousDataAccessMethod());
}
}
return await _getDataTask;
}
}
Your original code has the potential for this happening:
Thread 1 sees that _getDataTask == null, and begins constructing the task
Thread 2 sees that _getDataTask == null, and begins constructing the task
Thread 1 finishes constructing the task, which starts, and Thread 1 waits on that task
Thread 2 finishes constructing a task, which starts, and Thread 2 waits on that task
You end up with two instances of the task running.
Use the lock function to prevent multiple calls to the database query section. Lock will make it thread safe so that once it has been cached all the other calls will use it instead of running to the database for fulfillment.
lock(StaticObject) // Create a static object so there is only one value defined for this routine
{
if(_getDataTask == null)
{
// Get data code here
}
return _getDataTask
}
Please rewrite your function as:
public Task<MyData> GetDataAsync()
{
if (_getDataTask == null)
{
_getDataTask = Task.Run(() => synchronousDataAccessMethod());
}
return _getDataTask;
}
This should not change at all the things that can be done with this function - you can still await on the returned task!
Please tell me if that changes anything.
Bit late to answer this but there is an open source library called LazyCache that will do this for you in two lines of code and it was recently updated to handle caching Tasks for just this sort of situation. It is also available on nuget.
Example:
Func<Task<List<MyData>>> cacheableAsyncFunc = () => myDataAccessObject.GetDataAsync();
var cachedData = await cache.GetOrAddAsync("myDataAccessObject.GetData", cacheableAsyncFunc);
return cachedData;
// Or instead just do it all in one line if you prefer
// return await cache.GetOrAddAsync("myDataAccessObject.GetData", myDataAccessObject.GetDataAsync);
}
It has built in locking by default so the cacheable method will only execute once per cache miss, and it uses a lamda so you can do "get or add" in one go. It defaults to 20 minutes sliding expiration but you can set whatever caching policy you like on it.
More info on caching tasks is in the api docs and you may find the sample app to demo caching tasks useful.
(Disclaimer: I am the author of LazyCache)

Dispatcher.BeginInvoke Method 'freezing' after second execution

I'm making a windows phone game with Unity3d and I have the need to call a method from the Unity thread asynchronously from the UI thread.
This all works, however with one particular method the first execution executes as expected however after the second it seems to lock up the game.
private async static Task<String> ShowDescriptionProductListing()
{
var x = await CurrentApp.LoadListingInformationAsync();
StringBuilder builder = new StringBuilder();
builder.AppendFormat("{0}\n{1}", x.Description,
x.ProductListings.FirstOrDefault().Value);
return builder.ToString();
}
public static void ShowDescrProduct()
{
string x = ShowDescriptionProductListing().Result;
MessageBox.Show(x);
}
I think the line:
var x = await CurrentApp.LoadListingInformationAsync();
Is most likely the culprit, however I'm having a hard time debugging it.
The class which 'holds' that method in unity is like so:
public static class HelperClass
{
public static void ShowDescrProduct()
{
Dispatcherr.InvokeOnUIThread(Tests.ShowDescrProduct); //The method above
}
}
Dispatcherr (Yeah i need to use namespaces haha) just holds two Action properties that I set inside the UI thread.
public void EnterUIThread(Action action)
{
Dispatcher.BeginInvoke(() =>
{
action();
});
}
private void Unity_Loaded()
{
Dispatcherr.InvokeUIThread = EnterUIThread; //One of the actions I just
//mentioned being assigned the above
//method
}
And it's in the EnterUIThread call to Dispatcher.BeginInvoke that it seems to get locked up, only after the first call - which is always successful.
Confusing me slightly to say the least.
Anyone able to give any insight?
Thanks in advance
You're calling Result on the asynchronous operation. This is going to cause the UI thread to block until the asynchronous operation finishes. The asynchronous operation needs to wait for the UI thread to be free so that the continuation to LoadListingInformationAsync can be scheduled in the UI thread.
Both operations are waiting on each other to finish. Deadlock.
You need to not block the UI thread while waiting for this operation to finish. You should await it instead, making ShowDescrProduct and async method.

Categories