Marshalling exception with code from the ShareTarget second window - c#

I'm having a hard time with some code I have that apparently struggles when called from the second window created by the ShareTarget contract (when you share something to the app, it opens in a small standalone window).
This is my code so far:
// Blur and resize the image to get the average HSL color
// Assume that stream is an IRandomAccessStream pointing to valid image data
HslColor hslMean;
using (RandomAccessStreamImageSource imageProvider = new RandomAccessStreamImageSource(stream))
using (BlurEffect blurEffect = new BlurEffect(imageProvider) { KernelSize = 256 })
{
Color mean = await DispatcherHelper.GetFromUIThreadAsync(async () =>
{
WriteableBitmap
blurred = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight),
result = await blurEffect.GetBitmapAsync(blurred, OutputOption.Stretch),
resized = result.Resize(1, 1, WriteableBitmapExtensions.Interpolation.Bilinear);
return resized.GetPixel(0, 0);
});
hslMean = mean.ToHsl();
}
Note: that DispatcherHelper.GetFromUIThreadAsync method just checks the thread access to the UI thread, and if needed it schedules the code to a CoreDispatcher object that was obtained with CoreApplication.MainView.CoreWindow.Dispatcher.
Problem: this code works 100% fine if my app is already open, as at that point that CoreDispatcher object has already been created by previous calls to that DispatcherHelper class, so the method just uses the stored dispatcher to schedule the work and it works fine. But, if the app is closed when the ShareTarget window is opened (so that DispatcherHelper has to create the dispatcher for the first time) the CoreApplication.MainView.CoreWindow line throws an exception. A very weird one:
COMException:
A COM call to an ASTA was blocked because the call chain originated in or passed through another ASTA. This call pattern is deadlock-prone and disallowed by apartment call control.
A COM call (IID: {638BB2DB-451D-4661-B099-414F34FFB9F1}, method index: 6) to an ASTA (thread 10276) was blocked because the call chain originated in or passed through another ASTA (thread 4112). This call pattern is deadlock-prone and disallowed by apartment call control.
So, I needed a way to make that method reliable even when being called from different windows. I've tried different options:
#1: Just invoking that code without dispatching to a different thread, as in theory I should be on the UI thread at this point ---> FAIL (The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)))
#2: Manually calling CoreApplication.MainView.CoreWindow.Dispatcher to dispatch that code block ---> FAIL (I get that weird COMException mentioned above)
#3: Manually using CoreApplication.MainView.Dispatcher to dispatch the code block (as it was the .CoreWindow part that spawned the exception) ---> FAIL (COMException: item not found)
#4: Using CoreApplication.GetCurrentView().CoreWindow.Dispatcher, CoreApplication.GetCurrentView().Dispatcher, Window.Current.CoreWindow.Dispatcher and Window.Current.Content.Dispatcher to schedule that code ---> FAIL (wrong thread again, I get the usual marshalling exception)
All these marshalling exception are thrown at the line result = await blurEffect.GetBitmapAsync(blurred, OutputOption.Stretch), so I suspect it might be something related to the Lumia Imaging SDK.
I mean, I'm quite sure that I am in fact on the UI thread, or otherwise I wouldn't have managed to create an instance of the WriteableBitmap class, right?
Why is it that I can create WriteableBitmap objects (and they need to be created on the UI thread as far as I know), but that GetBitmapAsync method from the Lumia SDK always throws that marshalling exception? I'm using it everywhere in my app without any problems, why is it that it just won't work from the ShareTarget window? Is there anything I need to do?
Thanks for your help!

Looks like this is a bug in the Lumia Imaging SDK (that was originally written for WP8.1, which didn't have multiple windows/dispatchers), so unless the call to the library is made from the dispatcher associated with the main app window (which of course can only be retrieved if the app is open in the background when the ShareTarget window pops up), it will just fail.
The only solution at this point is to replace that call to the Lumia SDK with some other code that doesn't rely on that particular library (in this case for example, it is possible to just get the ARGB array from the WriteableBitmap object and calculate the mean color manually).

Related

Run IVMRWindowlessControl9.GetCurrentImage() in background

I have a webcam control using DirectShow.NET. I've created a custom control to display video and capture an image from a webcam. I'm using that custom control in another WPF window. I have a function public Bitmap CaptureImage() in the custom control to abstract away a little bit of the DirectShow programming and simply return a Bitmap. Since the images are relatively large (1920x1080), the GetCurrentImage() function of the IVMRWindowlessControl9 takes quite a while to process (2-3 seconds). I've stepped through my code and can confirm that this call is the only one that takes a long time to process.
Because of this, the GUI thread in my main WPF window hangs, causing it to be unresponsive for a few seconds, so if I want to display a progress spinner while the image is being captured, it will just remain frozen.
Here is the code for CaptureImage():
public Bitmap CaptureImage()
{
if (!IsCapturing)
return null;
this.mediaControl.Stop();
IntPtr currentImage = IntPtr.Zero;
Bitmap bmp = null;
try
{
int hr = this.windowlessControl.GetCurrentImage(out currentImage);
DsError.ThrowExceptionForHR(hr);
if (currentImage != IntPtr.Zero)
{
BitmapInfoHeader bih = new BitmapInfoHeader();
Marshal.PtrToStructure(currentImage, bih);
...
// Irrelevant code removed
...
bmp = new Bitmap(bih.Width, bih.Height, stride, pixelFormat, new IntPtr(currentImage.ToInt64() + Marshal.SizeOf(bih)));
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
}
}
catch (Exception ex)
{
MessageBox.Show("Failed to capture image:" + ex.Message);
}
finally
{
Marshal.FreeCoTaskMem(currentImage);
}
return bmp;
}
In order to fix this, I've tried to run this as a background task as follows:
public async void CaptureImageAsync()
{
try
{
await Task.Run(() =>
{
CaptureImage();
});
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I've tried multiple ways to do this including using BackgroundWorkers, but it seems that any time I make this call asynchronously, it creates this error:
Unable to cast COM object of type 'DirectShowLib.VideoMixingRenderer9'
to interface type 'DirectShowLib.IVMRWindowlessControl9'. This
operation failed because the QueryInterface call on the COM component
for the interface with IID '{8F537D09-F85E-4414-B23B-502E54C79927}'
failed due to the following error: No such interface supported
(Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
The error always happens when on this line:
int hr = this.windowlessControl.GetCurrentImage(out currentImage);
Calling CaptureImage() synchronously yields normal results. The image is captured and everything works as intended. However, switching to using any kind of asynchronous functionality gives that error.
You are having two issues here. First of all the original slowliness of the API is behavior by design. MSDN mentions this as:
However, frequent calls to this method will degrade video playback performance.
Video memory might be pretty slow for read-backs - this is the 2-3 second processing problem, not the resolution of the image per se. Bad news is that it is highly likely that even polling snapshots from background thread is going to affect the visual stream.
This method was and is intended for taking sporadic snapshots, esp. those initiated by user interactively, not automated. Applications needing more intensive and automated, and those not affecting visual feed snapshots are supposed to intercept the feed before it is sent to video memory (there are options to do it, and most popular yet clumsy is use of Sample Grabber).
Second, you are likely to be hitting .NET threading issue described in this question, which triggers the mentioned exception. It is easy to use the same interface pointer in native code development by sneaky violating COM threading rules and passing the interface pointer between apartments. Since CLR is adding a middle layer between your code and COM object doing additional safety checks, you can no longer operate with the COM object/interfaces from background thread because COM threading rules are enforced.
I suppose you either have to keep suffering from long freezes associated with direct API calls, or add native code development that helps to bypass the freezes (especially, for example, a helper filter which captures frames before sending to video memory and in the same time implementing helper functionality for .NET caller to support background thread calls). Presumably you can also do all DirectShow related stuff in a pool of helper MTA threads which solve you the background thread caller problem, but in this case you will most likely need to move this code from your UI thread which is STA - I don't think it something people often, if at all, doing.

Can't show MessageBox while app is running in assigned access mode in windows 10

I have written a UWP-App and it all works fine (in debug and release mode). I've packaged my app and installed it on a tablet on which windows 10 is installed (I develope on a windows 10 desktop pc), still no issues.
But now I want to run my app in assigned access mode (kiosk mode) on this tablet and suddenly out of nowhere my messageboxes doesn't show up anymore and an error appears.
Because I'm working with the mvvm pattern I've written a helper class for showing messageboxes so I don't need to use Windows.UI in my ViewModels:
public class UserNotificationService : IUserNotificationService
{
public async Task ShowMessageDialogAsync(string message, string title = null)
{
MessageDialog messageDialog = title == null ? new MessageDialog(message) : new MessageDialog(message, title);
await ShowAsync(messageDialog);
}
// This method throws an error
private async Task ShowAsync(MessageDialog msgDialog)
{
// I've to do it like this because otherwise it won't work because I'm working on a different thread while calling this method
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.N‌​ormal, async () => {
await msgDialog.ShowAsync();
});
}
}
Error:
A COM call to an ASTA was blocked because the call chain originated in or passed through another ASTA. This call pattern is deadlock-prone and disallowed by apartment call control.
A COM call (IID: {638BB2DB-451D-4661-B099-414F34FFB9F1}, method index: 6) to an ASTA (thread 6992) was blocked because the call chain originated in or passed through another ASTA (thread 7188). This call pattern is deadlock-prone and disallowed by apartment call control. at: at Windows.ApplicationModel.Core.CoreApplicationView.get_CoreWindow()
I don't understand what is different while working with the assigned access in windows 10. Like mentioned above this error only appears when the app is running in the assigned access. In any other case all works fine (on the desktop pc and on the tablet).
So my question is:
Has anyone experienced a same issue while developing an app to run in the assigned access mode in windows 10?
Or has anyone an idea of how to solve this issue?
This may be crashing because you are using the MainView dispatcher, which will not work in a Windows 10 Assigned Access Mode app.
The recomendation is to use
CoreApplication.GetCurrentView().Dispatcher
instead of
CoreApplication.MainView.CoreWindow.Dispatcher
From "Kiosk apps for assigned access: Best Practices"
Each view or window has its own dispatcher. In assigned access mode, you should not use the MainView dispatcher, instead you should use the CurrentView dispatcher.

Accessing System.Drawing.Bitmap from GTK# Thread throws Object Currently in use elsewhere exception

Im trying to manipulate an image using system.drawing in GTk#.I want the UI to update the image on screen as soon as the user updates a textbox.To implement this i tried using the background worker from winforms,it worked but when the textbox is updated at a higher speed the application becomes stuck with no error.
So i took a look at multithreading in GTK here http://www.mono-project.com/docs/gui/gtksharp/responsive-applications/ and created a thread .
void textboxchanged()
{
Thread thr = new Thread (new ThreadStart (ThreadRoutine));
thr.Start ();
}
static void ThreadRoutine ()
{
LargeComputation ();
}
static void LargeComputation ()
{
image=new Bitmap(backupimage);
//Long image processing
}
It works poorly than the background worker throws up object currently in use elsewhere error here image=new Bitmap(backupimage); when the speed of entry in textbox is even a little fast.What im i doing wrong ?
Update 1 :
Im not processing the same image using 2 different threads that does 2 different operations at the same time.Im calling the thread that does the same operation before the old thread is complete.As in background worker i need a way to check if the old thread has completed working before launching the new one.So basically what im looking for is a way to check if an instance of the same thread
is running.In winforms i used to do if(backgroundworker.isbusy==false) then do stuff
Update 2
Solution with performance degradation
As suggested by #voo Replacing the global bitmap helped solve the issue.What i did was instead of using global bitmap.I created a global string(filename).Now i use img=new Bitmap(filename).Tried executing fast as i can no error came up.So inorder to update the GUI i used the invoke as suggested here mono-project.com/docs/gui/gtksharp/responsive-applications/.The thing is no error comes up and image gets updated,but when the typing operation is fast enough there a wait involved. Performance got degraded.This was not the case with background worker.Is there a way to improve performance.
At end of the large image processing operation method i added this to update GUI
Gtk.Application.Invoke (delegate {
MemoryStream istream=new MemoryStream();
img.Save (istream, System.Drawing.Imaging.ImageFormat.Png);
istream.Position = 0;
workimagepixbuff = new Gdk.Pixbuf (istream);
image1.Pixbuf = workimagepixbuff.ScaleSimple (400, 300, Gdk.InterpType.Bilinear);
});
// cannot directly convert Bitmap to Pixbuff,so doing this
The problem here is that you are processing an image at two places (two threads) on the same time and the image operation in .Net (GDI speaking) does not allow this.
Because you did not provided very much information I'm just guessing here.
When manipulating bitmap images in GDI, there are BitmapData behind the scene that needs to be locked and unlocked. This mechanism just make the picture available in memory for read/write. But AFAIK when you lock a BitmapData that is already locked you get a similar exception : System.InvalidOperationException, Bitmap region is already locked.
To me it sounds like you are getting this kind of error, but with other words because you are not explicitly locking bitmap data bits. GDI just tell you : "I would have to lock bitmap data bits but I can't because the object is already used (locked) elsewhere."
The solution here may be to try to synchronize bitmap usage (where bits locking may be involved) between thread whenever they may occur. So you may want to use the lock keyword or a similar mechanism:
So try something that looks like the following:
private static object _imageLock = new object();
static void LargeComputation ()
{
lock(_imageLock)
{
image=new Bitmap(backupimage);
//Long image processing ...
}
}
static void AnotherImageOperationSomewhereElse()
{
lock(_imageLock)
{
//Another image processing on backupImage or something derived from it...
}
}

Parallel and COM (Outlook MAPI) aqcuiring and releasing?

Ive checked already some answers, but still Im not convinced what is this right approach of acquiring and releasing COM objects in parallel.
In particular I use a Parallel.ForEach to increase performance, and inside it, it makes calls to MS.Outlook (2010 ExchangeServer). However, by releasing the COM objects I get occasionally COMExceptions.
What is the right approach of working with COM objects with the Parallel library ?
System.Threading.Tasks.Parallel.ForEach(myList, myItem =>
{
String freeBusySlots = "";
Outlook.Recipient myReceipient = null;
try
{
myReceipient = namespaceMAPI.CreateRecipient(myItem.ToString());
}
catch (Exception ex)
{
...
}
finally
{
if (myReceipient == null)
{
...
}
Marshal.ReleaseComObject(myReceipient ); // -> I get an exception here sometimes ... how to avoid this
myReceipient = null;
}
}); // Parllel.forEach
Outlook Object Model cannot be used from secondary threads. Sometimes it works, but it tends to bomb out at the most inappropriate moment.
As of Outlook 2013, Outlook will immediately raise an error if an OOM object is accessed from a secondary thread.
If your code is running from another application, keep in mind that all calls will be serialized to the main Outlook thread anyway so there is really no point using multiple threads.
Also note that Extended MAPI (C++ or Delphi only) or Redemption (which wraps Extended MAPI and can be accessed from any language - I am its author) can be used from multiple threads, but your mileage will vary depending on the particular MAPI provider (IMAP4 store provider is the worst).
As a general rule you should never be using ReleaseComObject. Instead just wait for the RCW object to be collected and let the GC do the work for you. Using this API correctly is extremely hard.
Additionally it's very likely that all of Outlooks COM objects live in the STA. If that is the case there is nothing gained by operating over them in parallel. Every call made from a background thread will simply be marashalled back to the foreground thread for processing. Hence the background thread will add no value, just confusion.
I'm not 100% certain these are STA objects but I'd be very surprised if they weren't.

OutOfMemory exception in WPF video rendering application with COM interop

We have a rich client application developed using WPF/C#.Net 4.0 which interops with in-house COM DLLs. Regular events are raised via this COM interface containing video data.
As part of the application we render video via Windows Media Foundation and have created interops to use Window Media Foundation. We have multiple WMF pipelines rendering different video at the same time.
The application runs for 6-8 hours rendering video. Private bytes remaining consistently steady during this time (say around 500-600MB).
At some point the application appears to hang, at this point private bytes increases very rapidly until the process consumes approximately 1.4GB of memory and crashes with an OutOfMemoryException.
We have reproduced this on 5 different workstations with different graphic cards (NVIDIA and ATI cards) and a mixture of Windows 7 32 and 64bit.
We have analyzed 3 dump files and found that the finalizer thread is waiting on a call to the ole32.GetToSTA() method. We are unable to determine what causes the finalizer thread to block and how to resolve this. I have pasted excerpts from three dumps we've been analyzing:
Dump 1)
Thread 2:ae0 is waiting on an STA thread efc
Thread 28:efc is calling a WaitForSingleObject. The handle it is waiting on is actually a thread handle 5ab4 which is thread id 14a4
Thread 130:14a4 has the following stack:
37f4fdf4 753776a6 ntdll!NtRemoveIoCompletion+0x15
37f4fe20 63301743 KERNELBASE!GetQueuedCompletionStatus+0x29
37f4fe74 6330d0db WMNetMgr!CNSIoCompletionPortNT::WaitAndServeCompletionsLoop+0x5e
37f4fe94 633199bf WMNetMgr!CNSIoCompletionPortNT::WaitAndServeCompletions+0x4c
37f4fecc 63312dbd WMNetMgr!CWorkThreadManager::CWorkerThread::ThreadMain+0xa2
37f4fed8 769b3677 WMNetMgr!CWMThread::ThreadFunc+0x3b
37f4fee4 77679f42 kernel32!BaseThreadInitThunk+0xe
37f4ff24 77679f15 ntdll!__RtlUserThreadStart+0x70
37f4ff3c 00000000 ntdll!_RtlUserThreadStart+0x1b
Dump2)
STA thread:
1127f474 75f80a91 ntdll!ZwWaitForSingleObject+0x15
1127f4e0 77411184 KERNELBASE!WaitForSingleObjectEx+0x98
1127f4f8 77411138 kernel32!WaitForSingleObjectExImplementation+0x75
1127f50c 63ae5f29 kernel32!WaitForSingleObject+0x12
1127f530 63a8eb2e WMNetMgr!CWMThread::Wait+0x78
1127f54c 63a8f128 WMNetMgr!CWorkThreadManager::CThreadPool::Shutdown+0x70
1127f568 63a76e10 WMNetMgr!CWorkThreadManager::Shutdown+0x34
1127f59c 63a76f2d WMNetMgr!CNSClientNetManagerHelper::Shutdown+0xdd
1127f5a4 63cd228e WMNetMgr!CNSClientNetManager::Shutdown+0x66
WARNING: Stack unwind information not available. Following frames may be wrong.
1127f5bc 63cd23a6 WMVCORE!WMCreateProfileManager+0xeef6
1127f5dc 63c573ca WMVCORE!WMCreateProfileManager+0xf00e
1127f5e8 63c62f18 WMVCORE!WMIsAvailableOffline+0x2ba3b
1127f618 63c19da6 WMVCORE!WMIsAvailableOffline+0x37589
1127f630 63c1aca2 WMVCORE!WMIsContentProtected+0x56e4
1127f63c 63c14bd7 WMVCORE!WMIsContentProtected+0x65e0
1127f650 113de6e8 WMVCORE!WMIsContentProtected+0x515
1127f660 113de513 wmp!CWMDRMReaderStub::CExternalStub::ShutdownInternalRefs+0x1d0
1127f674 113c1988 wmp!CWMDRMReaderStub::ExternalRelease+0x4f
1127f67c 1160a5b9 wmp!CWMDRMReaderStub::CExternalStub::Release+0x13
1127f6a4 1161745f wmp!CWMGraph::CleanupUpStream_selfprotected+0xbe
Finalizer thread is trying to switch to STA:
0126eccc 75f80a91 ntdll!ZwWaitForSingleObject+0x15
0126ed38 77411184 KERNELBASE!WaitForSingleObjectEx+0x98
0126ed50 77411138 kernel32!WaitForSingleObjectExImplementation+0x75
0126ed64 75d78907 kernel32!WaitForSingleObject+0x12
0126ed88 75e9a819 ole32!GetToSTA+0xad
Dump3)
The finalizer thread is in the GetToSTA call, so it is waiting for a COM object to free
Thread 29 is a COM object in the STA, and it is waiting on a critical section owned by thread 53 (1bf4)
Thread 53 is doing:
1cbcf990 76310a91 ntdll!ZwWaitForSingleObject+0x15
1cbcf9fc 74cb1184 KERNELBASE!WaitForSingleObjectEx+0x98
1cbcfa14 74cb1138 kernel32!WaitForSingleObjectExImplementation+0x75
1cbcfa28 65dfb6bb kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
1cbcfa48 74cb3677 wmp!Ordinal3000+0x53280
1cbcfa54 77029f42 kernel32!BaseThreadInitThunk+0xe
1cbcfa94 77029f15 ntdll!__RtlUserThreadStart+0x701cbcfaac 00000000 ntdll!_RtlUserThreadStart+0x1b
Any ideas on how we might resolve this issue?
Well, the finalizer thread is deadlocked. That will certainly result in an eventual OOM. We can't see the full stack trace for the finalizer thread but some odds that you'll see SwitchAptAndDispatchCall() and ReleaseRCWListInCorrectCtx() in the trace, indicating that it is trying to call IUnknown::Release() to release a COM object. And that object is apartment threaded so a thread switch is required to safely make the call.
I don't see any decent candidates in the stack traces you posted, possibly because you didn't get the right one or the thread is already busy shutting down due to the exception. Try to catch it earlier with a debugger break as soon as you see the virtual memory size climb.
The most common cause for a deadlock like this is violating the requirements for an STA thread. Which state that it must never block and must pump a message loop. The never-block requirement is typically easily met in a .NET program, the CLR will pump a message loop when necessary when you use the lock statement or a WaitHandle.WaitXxx() call. It is however very common to forget to pump a message loop, especially since doing so is kinda painful. Application.Run() is required.

Categories

Resources