Correct me if I am wrong, but I noticed that the thread selected from the pool via ThreadPool.QueueUserWorkItem(GoneFishing)apparently "swallows" any exception that occurs within that thread.
This caused us a lot of trouble as we have designed an ordered thread chain, so if a thread does not finish well all the following chain is scrambled.
What is the most convenient way to deal with this in a proper fashion ?
If you consider using .NET 4.0, any exceptions thrown by a Task are automatically propagated to the parent thread when the Task is joined. Have a look here: http://msdn.microsoft.com/en-us/library/dd997415.aspx
For other related solutions check this question: Safe to throw an exception created on another thread C#
Related
I can't figure out how threads of different types behave in UWP applications. First, in UWP it seems that UI thread is not a main thread, it's one of worker threads (I see this in the debugger when inserting breakpoints in event handlers and so on). My assumption is that CoreApplication.MainView.CoreWindow.Dispatcher.HasThreadAccess designates if the current thread a UI thread or not.
From my understanding some actions should behave differently depending on the type of the current thread. In particular, synchronous I/O methods should raise an exception that synchronous I/O is not allowed on UI thread.
For instance, File.Exists, File.Move or creating a file with FileStream constructor. I even actually got these exceptions earlier but now can't figure out how to reproduce them again. They all are mysteriously gone. Even if I put these methods directly in a button.Click handler (which executes on UI thread, I believe, HasThreadAccess is true), they still work.
I believe this code kept throwing InvalidOperationException back in 2016 Dec when I tested it last time:
private async void button_Click(object sender, RoutedEventArgs e)
{
if (File.Exists(Path.Combine(ApplicationData.Current.LocalFolder.Path, "log.txt")))
{
}
Or, maybe, the code was close but not equal to that, maybe I'm missing some important detail..
I need to find a way to make these exceptions reliably occur again so that I could correctly refactor the old synchronous library to async and test it thoroughly. Without exceptions being thrown, I can't actually be sure that on someone's else system this library won't crash due to these I/O threading issues.
Got it. For some weird reason, synchronous methods of System.IO namespace behave differently (in terms of threading) for disk folders in different locations.
This works:
FileStream fs = new FileStream(Path.Combine(ApplicationData.Current.LocalFolder.Path, "log.txt"), FileMode.OpenOrCreate);
The below crashes with 'System.InvalidOperationException' and message 'Synchronous operations should not be performed on the UI thread. Consider wrapping this method in Task.Run':
FileStream fs = new FileStream(#"C:\Temp\log.txt", FileMode.OpenOrCreate);
At the same time, if I run the latter on a worker thread rather than UI thread, I get accurate UnauthorizedAccessException telling me that Access is denied.
I.e. it seems that prohibition to run synchronous operations on UI thread does NOT concern folders (at least ApplicationData.Current.LocalFolder) where this I/O is allowed and does concern folders where this I/O is not allowed anyway. Maybe a bug in .NET code for UWP that wrong exception is thrown?
That's strange as I believe it should be no relation between threading and access control matters but at least I found a way to make UWP sync method crash in the way I needed.
EDIT:
Turns out it's the correct and expected behavior. When on UI thread, WinRT won't even try to access resources outside LocalFolder because it would cause internal deadlock (that's just how WinRT works under the hood). For LocalFolder access, using UI thread for sync I/O is allowed. That's why I'm getting InvalidOperationException (rather than UnauthorizedAccessException) on UI thread only when accessing resources outside LocalFolder.
The problem with UI thread will be with an object like file picker which can return location outside of LocalFolder (brokered file). Accessing such file on a worker thread won't throw UnauthorizedAccessException and will go just fine but on a UI thread we'll get InvalidOperationException because the file is outside LocalFolder. So, brokered files can only be accessed from a worker thread (either via natively async methods or via sync methods on a dedicated worker thread).
I'm trying to abort a task which internally creates a thread.
The problem is that the inner thread is trying to access a resource which is already disposed (since the parent task is already cancelled), and that causes an unhandled exception.
The code which creates the thread is a 'black box', an external DLL, so I cannot pass it a CancellationToken or so.
What can I do to make the task abort its inner threads? Or what is the solution for this situation?
Thanks
If you can't manage the threads yourself then the best you can do is handle the exception. Throw a try catch aound the black box call and respond appropriately in your own code.
If you can I'd be complaining to the provider of the black box though. They should give you the proper api for using their tools.
I updated my code to use Tasks instead of threads....
Looking at memory usage and CPU I do not notices any improvements on the multi-core PC, Is this expected?
My application essentially starts up threads/tasks in different objects when it runs...
All I'm doing is a simple
Task a = new Task(...)
a.Start();
There are various implications to using Tasks instead of Threads, but performance isn't a major one (assuming you weren't creating huge numbers of threads.) A few key differences:
The default TaskScheduler will use thread pooling, so some Tasks may not start until other pending Tasks have completed. If you use Thread directly, every use will start a new Thread.
When an exception occurs in a Task, it gets wrapped into an AggregateException that calling code can receive when it waits for the Task to complete or if you register a continuation on the Task. This is because you can also do things like wait on multiple Tasks to complete, in which case multiple exceptions can be thrown and aggregated.
If you don't observe an unhandled exception thrown by a Task, it will (well, may) eventually be thrown by the finalizer of the Task, which is particularly nasty. I always recommend hooking the TaskScheduler.UnobservedTaskException event so that you can at least log these failures before the application blows up. This is different from Thread exceptions, which show up in the AppDomain.UnhandledException event.
If you simply replaced every usage of Thread with Task and did no other changes I would expect virtually the same performance. The Task API is really just that, it's an API over an existing set of constructs. Under the hood it uses threads to schedule it's activities and hence has similar performance characteristics.
What's great about Task are the new things you can do with them
Composition with ContinueWith
Cancellation
Hierarchies
Etc ...
One great improvement of Takss vs. Threads is that you can easiely build chains of tasks. You can specify when a task should start after the previous task ("OnSuccess", "OnError", a.s.o.) and you can specify if there should be a synchronization context switch. That gives you the great opportunity to run a long running task in bakcground and after that a UI refershing task on the UI thread.
If you are using .Net 4.0 then you can use the Parallel.Invoke method like so
Parallel.Invoke(()=> {
// What ever code you add here will get threaded.
});
for more info see
http://msdn.microsoft.com/en-us/library/dd992634.aspx
You would see difference if your original or converted code do not utlize CPU completely. I.e. if original code always limited number of threads to 2, on quad-core machine it will run at about 50% load with manually created threads and potentially 100% load with tasks (if your tasks can be actaully paralellized). So it looks like either your original code was reasonable from performance point of view, or both implemetaion suffer issues showing similar underutiliztion of CPU.
I'm not (intentionally) using threads in my C# app. In fact my main method has a [STAThread], which I thought meant I'd only be using one thread.
Why then, would I be getting this error message?
Cross-thread operation not valid: Control 'messageLog' accessed from a thread other than the thread it was created on.
There are a couple of types which can cause your code to run on different threads without any explicit call to System.Threading. In particular FileSystemWatcher and BackgroundWorker come to mind. Are you using any of these types?
Also STAThread in no way limits the ability of your process to spawn threads. It instead sets the COM apartment type of the initial application thread.
Marking your main method with [STAThread] does not mean that you cannot spawn additional threads.
You don't really provide any information about what is triggering your code, so I can't be more specific, but any time you execute asynchronous code it will take place on another thread. Doing things like BeginInvoke on a delegate (or, for that matter, most methods that start with Begin--and definitely if they return an IAsyncResult--are async methods) will execute the code (and the callback) on another thread.
If you can provide some more detail about your situation, I can try to give more specific advice.
[STAThread] does not indicate that your application will be single threaded. It only indicates that the application will use threading a manner that allows other threads to execute while a particular thread is waiting for a time-consuming operation to complete.
As to why the cross threading exception is being thrown, a little more context is needed. What type of control is messageLog? What code accesses this control? Are you using any other controls that implicitly use threads (such as a BackgroundWorker)?
I have a program that will analyzes source code. It can recursively go through a directory to find all projects, and then recursively go through the project to find all source code.
I want to create a cancel process button, which allows the user to stop the code parsing. I run the code parsing in a background worker. I want to be able to watch for the cancel event.
The problem is figuring out how to edit my code so that it will go and check that item and return back to the GUI. The parsing process goes several methods deep.
In a much smaller process, I successfully use a thread-safe singleton that has a bool that says whether or not a cancel has been requested, and stop the loop where it is running.
What would be the best way of working this cancel request into my code?
EDIT: Here is an idea, inspired by John Saunders' answer.
What if I run a background thread in my processing thread that watches for the Cancel Singleton to change, and then throw an exception from that process? Does this seem like good practice? This does not work as intended
EDIT 2: John Saunders' answer seems to be the best for now. I will just throw my own exception when the Singleton is true for now. I'll wait to see if any other solutions are proposed
Thread.Abort is a bad idea, as it interrupts the thread at an arbitrary point - probably interrupts it where you'd least like to be interrupted.
Set a flag that it seen by the thread being cancelled. Check it at the beginning of each operation. The idea would be to identify places in the code where it is safe to stop, and to check the flag at only those points.
You may find it useful to throw an exception at those points. The exception should be one that is not caught by your code until it reaches the boundary between your code and the UI. At that point, your code would simply return.
You could use the Thread.Abort() function on your background worker thread. This throws a ThreadAbortException which you can catch in any of your methods but which will atomatically be rethrown at the end of the catch blocks.
Also all finally-blocks will be executed.
It sounds like you're using the .NET backgroundworker class. I think you can pass a object parameter into the RunWorkerAsync method which then becomes accessible to the background thread in the DoWork event handler argument.
You could then modify that object in the UI thread (for example update a boolean cancel property) and periodically check on it from your background process.
There are various ways to perform a cancel on threaded operations; all of which involve the periodic checking of a flag or other value to determine if the thread should continue operating or not.
I would not recommend throwing exceptions for this feature. First of all, cancelling is not an exceptional circumstance, and second, it's overkill for what you're trying to implement.
Instead, you could use a simple, thread-safe boolean flag as a static member of a class accessible from any thread, or use a synchronization object such as a named Mutex. Signalling the synchronization object would then allow the thread to know it must cancel.