Is UImage.AsPNG() thread safe? When using UImage.AsPNG() in Xamarin.iOS 6.3.5.43 from a separate thread, I'm getting a MonoTouch.UIKit.UIKitThreadAccessException.
From the Apple docs I cannot see that this method is required to be executed on the main thread.
I did not get this warning in the 6.2 branch.
Yes, it is thread-safe and it has been fixed in the recently released Xamarin.iOS 6.2.7.
The problem was that we had a discussion with Apple engineers about thread-safe API, and we made a mistake when we went through the information they'd given us. A bit more information is available in the bug report.
From the Apple docs I cannot see that this method is required to be executed on the main thread
Apple don't specify per-method thread safety for UIKit. Rather, this disclaimer is given in the main framework reference:
Note: For the most part, UIKit classes should be used only from an application’s main thread. This is particularly true for classes derived from UIResponder or that involve manipulating your application’s user interface in any way.
Going back to your original problem - UIKitThreadAccessException is thrown on debug builds by MonoTouch. It's intended to serve as a checker/debug tool to make sure you're not doing UIKit stuff on a secondary thread.
Because from iOS 4 certain UIKit methods (mainly those involving drawing to a graphics context) became thread safe there's a whitelist of methods that MonoTouch won't throw this exception for, which is available in the MonoTouch documentation.
I couldn't say whether UIImage.AsPNG() is or isn't thread safe...I don't think it is, but if I'm wrong - or you want to risk it - you can pass the --disable-thread-check flag to disable MonoTouch's automatic UIKit background thread checking. This blog post might be helpful.
Related
I'm new to threaded programming. (in XE7)
I'm nervous that I may have inadvertently called procedures that access the VCL from a thread. My understanding is that this is dangerous.
I've added the code below to some of my procedures that touch the VCL.
(*$IFDEF DEBUG *)
Assert((Windows.GetCurrentThreadId = System.MainThreadID), "Thread error");
(*$ENDIF *)
Hopefully, this will catch any calls I made to my VCL-accessing procedures while in a thread.
It occurred to me that if I could insert this code into some VCL low-level code, that it would be more effective at catching illegal VCL access from a thread.
I have never dug into the VCL code, so I'm asking for feedback. Is there some central place in the VCL code that would be a good place for this code?
TComponent.Create is a nice low level place, but I'm not concerned with controls being created. I'm more concerned with accessing properties (.Left, .Checked) etc.
TIA
This cannot be done.
One thing that goes a little bit in that direction is the TVirtualMethodInterceptor in System.Rtti. You could use that to hook all virtual methods of some common classes like TControl or TCheckbox. Things like SetChecked or SetBounds are implemented as virtual methods. So you might be able to hook these. But you'd still have to proxify every instance of these classes.
Look at the Delphi help for an example.
I have been asked to debug, and improve, a complex multithreaded app, written by someone I don't have access to, that uses concurrent queues (both GCD and NSOperationQueue). I don't have access to a plan of the multithreaded architecture, that's to say a high-level design document of what is supposed to happen when. I need to create such a plan in order to understand how the app works and what it's doing.
When running the code and debugging, I can see in Xcode's Debug Navigator the various threads that are running. Is there a way of identifying where in the source-code a particular thread was spawned? And is there a way of determining to which NSOperationQueue an NSOperation belongs?
For example, I can see in the Debug Navigator (or by using LLDB's "thread backtrace" command) a thread's stacktrace, but the 'earliest' user code I can view is the overridden (NSOperation*) start method - stepping back earlier in the stack than that just shows the assembly instructions for the framework that invokes that method (e.g. __block_global_6, _dispatch_call_block_and_release and so on).
I've investigated and sought various debugging methods but without success. The nearest I got was the idea of method swizzling, but I don't think that's going to work for, say, queued NSOperation threads. Forgive my vagueness please: I'm aware that having looked as hard as I have, I'm probably asking the wrong question, and probably therefore haven't formed the question quite clearly in my own mind, but I'm asking the community for help!
Thanks
The best I can think of is to put breakpoints on dispatch_async, -[NSOperation init], -[NSOperationQueue addOperation:] and so on. You could configure those breakpoints to log their stacktrace, possibly some other info (like the block's address for dispatch_async, or the address of the queue and operation for addOperation:), and then continue running. You could then look though the logs when you're curious where a particular block came from and see what was invoked and from where. (It would still take some detective work.)
You could also accomplish something similar with dtrace if the breakpoints method is too slow.
Several weeks late, but I am finally getting back to updating my MonoTouch iOS app with the new 6.0 version. For long running activities (my application makes services calls to the background and does image uploads), I use threading very similar to the examples. This all worked great until I upgraded. A typical pattern in an a Controller would look like:
protected void LogInButtonClicked(object sender, EventArgs e)
{
NetworkActivity.Start();
// start the request.
ThreadPool.QueueUserWorkItem ((cb) => {
var service = new ClientUserService();
var result = service.Login(this.UserName.Text, this.Password.Text);
// when done, switch back to UI.
this.InvokeOnMainThread (() => {
NetworkActivity.Stop();
// do the various other things to init the app on the UI thread.
}
});
}
The worked great on 5.x and never crashed. And it followed the published code guidelines. But now I immediately get the exception of UUIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread. I get that on my service call line (service.Login(...)).
So... I'm not exactly sure what I'm doing wrong here. I did go back and look at some of the newer samples. Some of them are using the task library (for example https://github.com/xamarin/mobile-samples/blob/master/MultiThreading/iOSMultiThreading/Screens/MainScreen_iPhone.cs), but that shouldn't preclude this QueueUserWorkItem method.
Question: did the threading model in Monotouch have a breaking change so that the above coding pattern is no longer supported?
Thanks. JB
Wrap this.UserName.Text and this.Password.Text in InvokeOnMainThread delegate. Monotouch expects that all work with UI elements is performed in the UI thread.
This feature was introduced a while ago in MonoTouch 5.4 (see New Library Features, Cross-thread UI Checks).
Now this is not a threading change (the code is executed as before) but simply extra checks to ensure people are warned about a common pitfall - that was often pretty hard to debug.
There are instructions if you want the old behaviour back. However be warned that your current code is broken and, while it might work 99% of the time, it might break badly for some people (e.g. such issues are often timing dependent, changing your code or using different devices might trigger the issue).
As such I strongly suggest you to fix such issues as you find them (your users will love you for it ;-) just like Ben described.
I am implementing a synchronization method inside my application. The main steps it will perform are:
Get XML content from a remote site
Parse this XML using IXMLDomDocument2
Update a Firebird database
The logic is quite complex, but it is working fine per se.
The problem is when I try to run it inside a separate thread. It is clear to me that I am not getting thread safety properly in my logic.
So let´s slice it
I - Get content using TidHTTP
Didn´t have any problems with it, should I have any concerns here?
II - For IXMLDomDocument2 I am calling
CoInitializeEx(nil, 0);
which according to the documentation should be enough to use IXMLDomDocument2 safely. And it seems to be ok, after adding it I did not get any error when trying to use it. Any extra concern here?
III - To use Firebird safely
My problems are here. Sometimes it works, sometimes it don´t (which I guess is the main symptom of badly designed thread logic). Most of the time I get a EInterbaseError with the message "Error reading data from the connection". Other times it simply locks.
Should I have a separate connection with the database?
Warren nailed the main problem with sharing the connection between the background and foreground thread... you have another issue and that is every call to CoInitialize needs to be paired with CoUninitialize
http://msdn.microsoft.com/en-us/library/windows/desktop/ms688715(v=vs.85).aspx
In WinForms, pretty much all your UI is thread-specific. You have to use [STAThread] so that the common dialogs will work, and you can't (safely) access a UI element from any thread other than the one that created it. From what I've heard, that's because that's just how Windows works -- window handles are thread-specific.
In WPF, these same restrictions were kept, because ultimately it's still building on top of the same Windows API, still window handles (though mostly just for top-level windows), etc. In fact, WPF even made things more restrictive, because you can't even access things like bitmaps across threads.
Now along comes WinRT, a whole new way of accessing Windows -- a fresh, clean slate. Are we still stuck with the same old threading restrictions (specifically: only being able to manipulate a UI control from the thread that created it), or have they opened this up?
I would expect it to be the same model - but much easier to use, at least from C# and VB, with the new async handling which lets you write a synchronous-looking method which just uses "await" when it needs to wait for a long-running task to complete before proceeding.
Given the emphasis on making asynchronous code easier to write, it would be surprising for MS to forsake the efficiency of requiring single-threaded access to the UI at the same time.
The threading model is identical. There is still a notion of single threaded and multi-threaded apartments (STA/MTA), it must be initialized by a call to RoInitialize. Which behaves very much like CoInitialize in name, argument and error returns. The user interface thread is single threaded, confirmed at 36:00 in this video.
The HTML/CSS UI model is inherently single threaded (until the advent of web workers recently, JS didn't support threads). Xaml is also single threaded (because it's really hard for developers to write code to a multithreaded GUI).
The underlying threading model does have some key differences. When your application starts, an ASTA (Application STA) is created to run your UI code as I showed in the talk. This ASTA does not allow reentrancy - you will not receive unrelated calls while making an outgoing call. This is a significant difference from STAs.
You are allowed to create async workitems - see the Windows.System.Threadpool namespace. These workitem threads are automatically initialized to MTA. As Larry mentioned, webworkers are the JS equivalent concept.
Your UI components are thread affined. See the Windows.UI.Core.CoreDispatcher class for information on how to execute code on the UI thread. You can check out the threading sample for some example code to update the UI from an async operation.
Things are different in pretty important ways.
While it's true the underlying threading model is the same, your question is generally related to how logical concurrency works with UI, and with respect to this what developers see in Windows 8 will be new.
As you mention most dialogs previously blocked. For Metro apps many UI components do not block all. Remember the talk of WinRT being asynchronous? It applies to UI components also.
For example this .NET 4 code will not necessarily kill your harddrive because the UI call blocks on Show (C# example):
bool formatHardDrive = true;
if (MessageBox.Show("Format your harddrive?") == NO)
formatHardDrive = false;
if (formatHardDrive == true)
Format();
With Windows 8 Metro many UI components like Windows.UI.Popups.MessageDialog, are by default Asynchronous so the Show call would immediately (logically) fall through to the next line of code before the user input is retrieved.
Of course there is an elegant solution to this based on the await/promise design patterns (Javascript example):
var md = Windows.UI.Popups.MessageDialog("Hello World!");
md.showAsync().then(function (command) {
console.log("pressed: " + command.label); });
The point is that while the threading model doesn't change, when most people mention UI and threading they are thinking about logical concurrency and how it affects the programming model.
Overall I think the asynchronous paradigm shift is a positive thing. It requires a bit of a shift in perspective, but it's consistent with the way other platforms are evolving on both the client and server sides.