I try to resolve the dreaded .WindowsPhone.exe!{<ID>}_Quiesce_Hang hang issue of my WinRT (Windows Phone 8.1) app.
At the moment I have the following handling of the Windows.UI.Xaml.Application.Suspending event:
private void App_Suspending(object iSender, SuspendingEventArgs iArgs)
{
SuspendingDeferral clsDeferral = null;
object objLock = new object();
try
{
clsDeferral = iArgs.SuspendingOperation.GetDeferral();
DateTimeOffset clsDeadline = iArgs.SuspendingOperation.Deadline;
//This task is to ensure that the clsDeferral.Complete()
//is called before the deadline.
System.Threading.Tasks.Task.Run(
async delegate
{
//Reducing the timeout by 1 second just in case.
TimeSpan clsTimeout = clsDeadline.Subtract(DateTime.UtcNow).Subtract(TimeSpan.FromSeconds(1));
if (clsTimeout.TotalMilliseconds > 100)
{
await System.Threading.Tasks.Task.Delay(clsTimeout);
}
DeferrerComplete(objLock, ref clsDeferral);
});
//Here I execute the suspending code i.e. I serializing the app
//state and save it in files. This may take more than clsTimeout
//on some devices.
...
//I do not call the Complete method here because the above
//suspending code is old-fashoin asynchronous i.e. not async but
//returns before the job is done.
//DeferrerComplete(objLock, ref clsDeferral);
}
catch
{
DeferrerComplete(objLock, ref clsDeferral);
}
}
private static void DeferrerComplete(object iLock, ref SuspendingDeferral ioDeferral)
{
lock (iLock)
{
if (ioDeferral != null)
{
try
{
ioDeferral.Complete();
}
catch
{
}
ioDeferral = null;
}
}
}
I have read the answer about the _Quiesce_Hang problem. I get the idea that it might be related to app storage activity. So my question is: what am I missing? Does my handling of the Suspending event look OK?
Related
I am trying to access the Microsoft Store from a multi-threaded program. The program itself work well - no problems there, but the method
Windows.Foundation.IAsyncOperation<StorePurchaseResult> purchase = product.RequestPurchaseAsync();
throws the exception:
"Invalid window handle.\r\n\r\nThis function must be called from a UI
thread"
My code is as follows...
private void testButton_Click(object sender, EventArgs e)
{
//Dispatcher dispUI = Dispatcher.CurrentDispatcher;
//dispUI.BeginInvoke((ThreadStart)delegate ()
//{
// _ = SetStore();
//});
//Dispatcher.BeginInvoke(new Action(TestStuff));
_ = SetStore();
}
[ComImport]
[Guid("4AEEEC08-7C92-4456-A0D6-1B675C7AC005")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IInitializeWithWindow
{
void Initialize(IntPtr hwnd);
}
private async Task SetStore()
{
try
{
StoreContext theStore = StoreContext.GetDefault();
// "Unable to cast object of type 'Windows.Services.Store.StoreContext' to type 'IInitializeWithWindow'."
// IInitializeWithWindow initWindow = (IInitializeWithWindow)(object)theStore;
// initWindow.Initialize(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle);
StoreProductResult app = await theStore.GetStoreProductForCurrentAppAsync();
// This works...
StoreProduct product = app.Product;
string title = product.Title;
string price = product.Price.FormattedPrice;
// This works...
StoreAppLicense license = await theStore.GetAppLicenseAsync();
bool trial = license.IsTrial;
bool full = license.IsActive;
// "Invalid window handle.\r\n\r\nThis function must be called from a UI thread"
StorePurchaseResult result = await theStore.RequestPurchaseAsync("9NRFBVGVGW8K");
// "Invalid window handle.\r\n\r\nThis function must be called from a UI thread"
// Windows.Foundation.IAsyncOperation<StorePurchaseResult> purchase = product.RequestPurchaseAsync();
}
catch (Exception e)
{
int a = 1;
}
}
I have associated the VS2019 UWP installer project with the store, which I figure is why the other methods return the right answers without needing to cast the store object with IInitializeWithWindow (which also throws an error, but which bypassing seems to let the code work).
I figure I have to tap into the UI thread somehow - go no idea how. Various examples from all over the place don't seem to work for me. Can anyone help me?
EDIT: This is a .Net program with a UWP wrapper creating a MSIX package.
For UWP, you need to use the following bit of code to call to the UI thread:
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
//UI code here
});
Try following, It works for me for .net 6 wpf app
WinRT.Interop.InitializeWithWindow.Initialize(storeContext, new WindowInteropHelper(window).Handle);
I have some code that loads up and AppDomain(call it domain) calling an object function within the domain. The purpose is to get a list of items from a usb device using the device API to retrieve the information. The API requires a callback to return the information.
var AppDomain.CreateDomain(
$"BiometricsDomain{System.IO.Path.GetRandomFileName()}");
var proxy = domain.CreateInstanceAndUnwrap(proxy.Assembly.FullName, proxy.FullName
?? throw new InvalidOperationException()) as Proxy;
var ids = obj.GetIdentifications();
The proxy code loaded into the domain is as follows
public class Proxy : MarshalByRefObject
{
public List<String> GetIdentifications()
{
var control = new R100DeviceControl();
control.OnUserDB += Control_OnUserDB;
control.Open();
int nResult = control.DownloadUserDB(out int count);
// need to be able to return the list here but obviously that is not
// going to work.
}
private void Control_OnUserDB(List<String> result)
{
// Get the list of string from here
}
}
Is there a way to be able to wait on the device and return the information as needed when the callback is called? Since the GetIdentifications() has already returned I don't know how to get the
You can consider wrapping the Event-Based Asynchronous Pattern (EAP) operations as one task by using a TaskCompletionSource<TResult> so that the event can be awaited.
public class Proxy : MarshalByRefObject {
public List<String> GetIdentifications() {
var task = GetIdentificationsAsync();
return task.Result;
}
private Task<List<String>> GetIdentificationsAsync() {
var tcs = new TaskCompletionSource<List<string>>();
try {
var control = new R100DeviceControl();
Action<List<string>> handler = null;
handler = result => {
// Once event raised then set the
// Result property on the underlying Task.
control.OnUserDB -= handler;//optional to unsubscribe from event
tcs.TrySetResult(result);
};
control.OnUserDB += handler;
control.Open();
int count = 0;
//call async event
int nResult = control.DownloadUserDB(out count);
} catch (Exception ex) {
//Bubble the error up to be handled by calling client
tcs.TrySetException(ex);
}
// Return the underlying Task. The client code
// waits on the Result property, and handles exceptions
// in the try-catch block there.
return tcs.Task;
}
}
You can also improve on it by adding the ability to cancel using a CancellationToken for longer than expected callbacks.
With that the proxy can then be awaited
List<string> ids = proxy.GetIdentifications();
Reference How to: Wrap EAP Patterns in a Task
NOTE: Though there may be more elegant solutions to the problem of asynchronous processing, the fact that this occurs in a child AppDomain warrants child AppDomain best practices. (see links below)
i.e.
do not allow code meant for a child AppDomain to be executed in the parent domain
do not allow complex types to bubble to the parent AppDomain
do not allow exceptions to cross AppDomain boundaries in the form of custom exception types
OP:
I am using it for fault tolerance
First I would probably add a Open or similar method to give time for the data to materialise.
var proxy = domain.CreateInstanceAndUnwrap(proxy.Assembly.FullName, proxy.FullName
?? throw new InvalidOperationException()) as Proxy;
proxy.Open(); // <------ new method here
.
. some time later
.
var ids = obj.GetIdentifications();
Then in your proxy make these changes to allow for data processing to occur in the background so that by the time you call GetNotifications data may be ready.
public class Proxy : MarshalByRefObject
{
ConcurrentBag<string> _results = new ConcurrentBag<string>();
public void Open()
{
var control = new R100DeviceControl();
control.OnUserDB += Control_OnUserDB;
control.Open();
// you may need to store nResult and count in a field?
nResult = control.DownloadUserDB(out int count);
}
public List<String> GetIdentifications()
{
var copy = new List<string>();
while (_results.TryTake(out var x))
{
copy.Add(x);
}
return copy;
}
private void Control_OnUserDB(List<String> result)
{
// Get the list of string from here
_results.Add (result);
}
}
Now you could probably improve upon GetNotifications to accept a timeout in the event either GetNotifications is called before data is ready or if you call it multiply but before subsequent data to arrive.
More
How to: Run Partially Trusted Code in a Sandbox
Not sure why you just don't maintain a little state and then wait for the results in the call:
public class Proxy : MarshalByRefObject
{
bool runningCommand;
int lastResult;
R100DeviceControl DeviceControl { get{ if(deviceControl == null){ deviceControl = new R100DeviceControl(); deviceControl.OnUserDB += Control_OnUserDB; } return deviceControl; } }
public List<String> GetIdentifications()
{
if(runningCommand) return null;
DeviceControl.Open();
runningCommand = true;
lastResult = control.DownloadUserDB(out int count);
}
private void Control_OnUserDB(List<String> result)
{
runningCommand = false;
// Get the list of string from here
}
}
Once you have a pattern like this you can easily switch between async and otherwise whereas before it will look a little harder to understand because you integrated the async logic, this way you can implement the sync method and then make an async wrapper if you desire.
I've search on stackoverflow and also in net and I couldn't find solution to my problem.
I read from a stream in async way. I want callback to update gui
[STAThread]
private void ClientLoggedCallback(IAsyncResult res)
{
try
{
MailClient.Helpers.Client.getInstance().client.GetStream().EndWrite(res);
MailClient.Helpers.Client.getInstance().asyncRecieveEncryptedProtocolMessage(new AsyncCallback(LoginInfo_recieved));
}
catch { }
}
[STAThread]
private void LoginInfo_recieved(IAsyncResult res)
{
try
{
MailClient.Helpers.Client.getInstance().client.GetStream().EndRead(res);
MailClient.AsyncState state = (MailClient.AsyncState)res.AsyncState;
string answer = Aes.DecryptStringFromBytes_Aes(state.buffer, state.AES_KEY, state.AES_IV);
if (answer.Contains("OK"))
{
string[] answer_params = answer.Split(',');
LoggedUserInfo.USER_ID = Convert.ToInt32(answer_params[1]);
LoggedUserInfo.USER_LOGIN = answer_params[2];
//zalogowano
//this.TargetWindow = new MessageListsWindow();
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(() => this.TargetWindow = new MessageListsWindow()));
//System.Windows.Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => this.TargetWindow = new MessageListsWindow()));
}
else
{
//zle dane
System.Windows.MessageBox.Show("Zle dane");
}
}
catch(Exception exep) { }
}
This is declaration of asyncSendEncryptedProtocolMessage
asyncSendEncryptedProtocolMessage(string message, AsyncCallback callBack)
use function
clientStream.BeginWrite(encryptedMessage, 0, encryptedMessage.Length, callBack, st);
when code executes I get exception "The calling thread must be STA, because many UI components require this." I read about "SetApartmentState(ApartmentState.STA);" but I don't know how to apply it to callback. I've also tried with STAThread attribute but it doesn't work. I use MVVM Light framework.
StackTrace
" w System.Windows.Threading.DispatcherObject.VerifyAccess()\r\n w System.Windows.Application.get_MainWindow()\r\n w MailClient.ViewModel.MainWindowModel.LoginInfo_recieved(IAsyncResult res) w c:\\Users\\oem\\Documents\\Visual Studio 2012\\Projects\\MvvmLight3\\MailClient\\ViewModel\\MainWindowModel.cs:wiersz 171"
public static void Dispatch(this DispatcherObject source, Action func)
{
if (source.Dispatcher.CheckAccess())
func();
else
source.Dispatcher.Invoke(func);
}
And then use it like this:
MailClient.Helpers.Client.getInstance()
.asyncRecieveEncryptedProtocolMessage(new AsyncCallback(()=>
Application.Current.MainWindow.Dispatch(LoginInfo_recieved)));
I'm trying to test the Internet connection in Windows8 from my C# application. I have a variable of type Boolean that returns me the connection status. When the boolean is true: do nothing. When the boolean becomes false, load my "NetworkDisconection" page. However, when I debug this line:
if (this.Frame != null)
I get an exception:
The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
Yeah, this method is on a different thread. How can I resolve this?
private bool bConection;
public HUB()
{
this.InitializeComponent();
bConection = NetworkInformation.GetInternetConnectionProfile()!= null;
NetworkInformation.NetworkStatusChanged += NetworkInformation_NetworkStatusChanged;
}
void NetworkInformation_NetworkStatusChanged(object sender)
{
if (NetworkInformation.GetInternetConnectionProfile() == null)
{
if (bConection == false)
{
bConection = true;
}
}
else
{
if (bConection == true)
{
bConection = false;
if (this.Frame != null)
{
Frame.Navigate(typeof(NetworkDisconection));
}
}
}
}
Use the following code and it should fix your problem...
Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (this.Frame != null)
{
Frame.Navigate(typeof(NetworkDisconection));
}
});
You should be able to acquire the Dispatcher directly since it looks like your code is in the code-behind of a XAML page (reference to this.Frame).
Tons of good info can be found in the C# Win8 Dev Forums. Search for Dispatcher and you will find several discussions on it. As always, check out GenApp for other great resources.
The NetworkInformation.NetworkStatusChanged event is raised on a non-UI thread. Similar to WinForms and WPF, you are still limited to accessing controls on the UI thread.
To get around this aspect, you'll have to invoke the UI thread similar to how you would on WinForms or WPF using this.Invoke/this.Dispatcher.Invoke.
At first you may try to use Window.Current.Dispatcher.RunAsync() but you will notice that Window.Current is always null here.
Instead, you should use CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync() in the Windows.ApplicationModel.Core namespace. Yeah, that's quite a mouthful for sure so I recommend this helper method in App.cs.
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
public static IAsyncAction ExecuteOnUIThread(DispatchedHandler action)
{
var priority = CoreDispatcherPriority.High;
var dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher;
return dispatcher.RunAsync(priority, action);
}
I would also recommend this helper method too:
public static bool CheckInternetAccess()
{
var profile = NetworkInformation.GetInternetConnectionProfile();
if (profile == null) return false;
var connectivityLevel = profile.GetNetworkConnectivityLevel();
return connectivityLevel.HasFlag(NetworkConnectivityLevel.InternetAccess);
}
And finally:
async void NetworkInformation_NetworkStatusChanged(object sender)
{
var isConnected = CheckInternetAccess();
await ExecuteOnUIThread(() =>
{
if (!isConnected && this.Frame != null)
this.Frame.Navigate(typeof(ConnectionLostPage));
});
}
I need to synchronize a sequence of operations that contains an asynchronous part.
The method looks into an image cache and returns the image if it's there (invokes a callback in reality). Otherwise it has to download it from the server. The download operation is asynchronous and fires an event on completion.
This is the (simplified) code.
private Dictionary<string, Bitmap> Cache;
public void GetImage(string fileName, Action<Bitmap> onGetImage)
{
if (Cache.ContainsKey(fileName))
{
onGetImage(Cache[fileName]);
}
else
{
var server = new Server();
server.ImageDownloaded += server_ImageDownloaded;
server.DownloadImageAsync(fileName, onGetImage); // last arg is just passed to the handler
}
}
private void server_ImageDownloaded(object sender, ImageDownloadedEventArgs e)
{
Cache.Add(e.Bitmap, e.Name);
var onGetImage = (Action<Bitmap>)e.UserState;
onGetImage(e.Bitmap);
}
The problem: if two threads call GetImage almost at the same time, they will both call the server and try to add the same image to the cache. What I should do is create lock at the beginning of GetImage and release it at the end of the server_ImageDownloaded handler.
Obviously this is not doable with the lock construct and it would not make sense, because it would be difficult to ensure that the lock is realeased in any case.
Now what I thought I could do is use a lambda instead of the event handler. This way I can put a lock around the whole section:
I have to lock the Cache dictionary at the beginning of the DownloadImage method and release it only at the end of the ImageDownloaded event handler.
private Dictionary<string, Bitmap> Cache;
public void GetImage(string fileName, Action<Bitmap> onGetImage)
{
lock(Cache)
{
if (Cache.ContainsKey(fileName))
{
onGetImage(Cache[fileName]);
}
else
{
var server = new Server();
server.ImageDownloaded += (s, e) =>
{
Cache.Add(e.Bitmap, e.Name);
onGetImage(e.Bitmap);
}
server.DownloadImageAsync(fileName, onGetImage); // last arg is just passed to the handler
}
}
}
Is this safe? Or the lock is immediately released after execution of GetImage, leaving the lambda expression unlocked?
Is there a better approach to solve this problem?
SOLUTION
In the end the solution was a bit of a mix of all the answers and comments, unfortunately I cannot mark-as-answer all of them. So here is my final code (removed some null checks/error cases/etc. for clarity).
private readonly object ImageCacheLock = new object();
private Dictionary<Guid, BitmapImage> ImageCache { get; set; }
private Dictionary<Guid, List<Action<BitmapImage>>> PendingHandlers { get; set; }
public void GetImage(Guid imageId, Action<BitmapImage> onDownloadCompleted)
{
lock (ImageCacheLock)
{
if (ImageCache.ContainsKey(imageId))
{
// The image is already cached, we can just grab it and invoke our callback.
var cachedImage = ImageCache[imageId];
onDownloadCompleted(cachedImage);
}
else if (PendingHandlers.ContainsKey(imageId))
{
// Someone already started a download for this image: we just add our callback to the queue.
PendingHandlers[imageId].Add(onDownloadCompleted);
}
else
{
// The image is not cached and nobody is downloading it: we add our callback and start the download.
PendingHandlers.Add(imageId, new List<Action<BitmapImage>>() { onDownloadCompleted });
var server = new Server();
server.DownloadImageCompleted += DownloadCompleted;
server.DownloadImageAsync(imageId);
}
}
}
private void DownloadCompleted(object sender, ImageDownloadCompletedEventArgs e)
{
List<Action<BitmapImage>> handlersToExecute = null;
BitmapImage downloadedImage = null;
lock (ImageCacheLock)
{
if (e.Error != null)
{
// ...
}
else
{
// ...
ImageCache.Add(e.imageId, e.bitmap);
downloadedImage = e.bitmap;
}
// Gets a reference to the callbacks that are waiting for this image and removes them from the waiting queue.
handlersToExecute = PendingHandlers[imageId];
PendingHandlers.Remove(imageId);
}
// If the download was successful, executes all the callbacks that were waiting for this image.
if (downloadedImage != null)
{
foreach (var handler in handlersToExecute)
handler(downloadedImage);
}
}
The lambda expression is converted into a delegate within a lock, but the body of the lambda expression will not automatically acquire the lock for the Cache monitor when the delegate is executed. So you may want:
server.ImageDownloaded += (s, e) =>
{
lock (Cache)
{
Cache.Add(e.Bitmap, e.Name);
}
onGetImage(e.Bitmap);
}
You have another potential problem here. This code:
if (Cache.ContainsKey(fileName))
{
onGetImage(Cache[fileName]);
}
If some other thread removes the image from the cache after your call to ContainsKey but before the next line is executed, it's going to crash.
If you're using Dictionary in a multi-threaded context where concurrent threads can be reading and writing, then you need to protect every access with a lock of some kind. lock is convenient, but ReaderWriterLockSlim will provide better performance.
I would also suggest that you re-code the above to be:
Bitmap bmp;
if (Cache.TryGetValue(fileName, out bmp))
{
onGetImage(fileName);
}
If you're running .NET 4.0, then I would strongly suggest that you look into using ConcurrentDictionary.
Why don't you just keep a a collection of image filenames that are being downloaded, and have the code for a thread be:
public void GetImage(string fileName, Action<Bitmap> onGetImage)
{
lock(Cache)
{
if (Cache.ContainsKey(fileName))
{
onGetImage(Cache[fileName]);
}
else if (downloadingCollection.contains(fileName))
{
while (!Cache.ContainsKey(fileName))
{
System.Threading.Monitor.Wait(Cache)
}
onGetImage(Cache[fileName]);
}
else
{
var server = new Server();
downloadCollection.Add(filename);
server.ImageDownloaded += (s, e) =>
{
lock (Cache)
{
downloadCollection.Remove(filename);
Cache.Add(e.Bitmap, e.Name);
System.Threading.Monitor.PulseAll(Cache);
}
onGetImage(e.Bitmap);
}
server.DownloadImageAsync(fileName, onGetImage); // last arg is just passed to the handler
}
}
}
That is more or less the standard monitor pattern, or would be if you refactored the lambda expression into a member function like GetImage. You should really do that. It will make the monitor logic easier to reason about.