I have the following code:
ShowPoup();
if (_watcher == null)
{
_watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
_watcher.MovementThreshold = 15; // use MovementThreshold to ignore noise in the signal
_watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
}
if (!_watcher.TryStart(true, TimeSpan.FromSeconds(3)))
{
MessageBox.Show("Please turn on location services on device under Settings.");
//HidePopup();
}
My problem is that the popup doesn't appear until after the _watcher.TryStart() method returns. The point of the popup is to show a loading overlay to tell the user the app is doing something. It's pointless to have it show after the work is done, at which point I hide the popup, so the user never sees anything.
I have this popup code throughout the app and this is the first time I've encountered this issue. Even if I call ShowPopup() in a separate method before calling the current method, it still doesn't show until after _watcher starts. I'm not sure why this is happening.
It looks like you are blocking the UI thread during the TryStart. If you can move the watcher initialization to a background thread (e.g. to the threadpool) then you can keep the display "alive".
Something like:
ShowPoup();
if (_watcher == null)
{
_watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
_watcher.MovementThreshold = 15; // use MovementThreshold to ignore noise in the signal
_watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);
}
System.Threading.ThreadPool.QueueUserWorkItem((ignored) =>
{
if (!_watcher.TryStart(true, TimeSpan.FromSeconds(3)))
{
Dispatcher.BeginInvoke(() =>
{
HidePopup();
MessageBox.Show("Please turn on location services on device under Settings.");
}
});
});
Related
PROBLEM
I am using a secondary view to run my media files, but When I close my secondary view with close button on it ( while media is still playing ) the secondary view/window closes but the media somehow keeps playing because I can hear the sound and source of sound seems to be the primary view ( main app window ). how can I completely terminate the secondary window when I close it?
TRIED
I followed windows samples multiple views and was able to complete all steps, I copied the ViewLifetimeControl.cs file from the sample and used it in my project. the code runs fine until it reaches Windows.Current.Close() in released event of the secondary view.
Then it gives an exception when it tries "Window.Current.Close()" with in the released event. according to documentation exception occurs due to any on going changes ( which might be because of media file playing ), but I need to force close the window even when media file is playing how can I do that? btw here is the exception :
Message = "COM object that has been separated from its underlying RCW cannot be used."
Code to Create and Show secondary view
internal static async Task CompactOpen(string Title, string caption)
{
ViewLifetimeControl viewControl = null;
await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
viewControl = ViewLifetimeControl.CreateForCurrentView();
viewControl.Title = Title;
viewControl.StartViewInUse();
var frame = new Frame();
frame.MinHeight = 200;
frame.MinWidth = 200;
frame.Navigate(typeof(CompactNowPlayingPage), new object[] { viewControl,caption});
Window.Current.Content = frame;
Window.Current.Activate();
ApplicationView.GetForCurrentView().Title = viewControl.Title;
});
((App)App.Current).SecondaryViews.Add(viewControl);
var selectedView = viewControl;
var sizePreference = new SizePreferenceString() { Title = "SizePreference", Preference = ViewSizePreference.Default };
var anchorSizePreference = new SizePreferenceString() { Title = "AnchorSizePreference", Preference = ViewSizePreference.Default };
if (selectedView != null && sizePreference != null && anchorSizePreference != null)
{
try
{
selectedView.StartViewInUse();
var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(
selectedView.Id,
sizePreference.Preference,
ApplicationView.GetForCurrentView().Id,
anchorSizePreference.Preference);
if (!viewShown)
{
// The window wasn't actually shown, so release the reference to it
// This may trigger the window to be destroyed
}
// Signal that switching has completed and let the view close
selectedView.StopViewInUse();
}
catch (InvalidOperationException)
{
// The view could be in the process of closing, and
// this thread just hasn't updated. As part of being closed,
// this thread will be informed to clean up its list of
// views (see SecondaryViewPage.xaml.cs)
}
}
}
Released Event
private async void ViewLifetimeControl_Released(Object sender, EventArgs e)
{
((ViewLifetimeControl)sender).Released -= ViewLifetimeControl_Released;
// The ViewLifetimeControl object is bound to UI elements on the main thread
// So, the object must be removed from that thread
await mainDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
((App)App.Current).SecondaryViews.Remove(thisViewControl);
});
// The released event is fired on the thread of the window
// it pertains to.
//
// It's important to make sure no work is scheduled on this thread
// after it starts to close (no data binding changes, no changes to
// XAML, creating new objects in destructors, etc.) since
// that will throw exceptions
Window.Current.Close(); //this is where that exception occurs
}
Note : both of above methods and even all the related variables, all of them I have followed the guidelines within the uwp sample for multiple views.
Thanks in advance, any help would be really appreciated, I only want to force close the secondary view ( If that's possible )
Is this in the editor or the app? If it's in your debug or build of the app, the secondary view is most likely still open but hidden. You may be using a custom close button which doesn't perform its job well enough. Instead of putting down SecondaryViews.Remove you should do what you had originally written and try StopViewInUse. It may not work, I'm not used to this kind of thing.
so after more than a week of trying to solve it on my own I officially give up and turn to your help. Basically, it should not be so complicated so I have no idea why it does not work. I have a WPF app which contains a Main Window called surprise surpise...: Main_Window.
That window contain a user control called 'pageTransitionControl' that change its content according to what the client want to see. the 'pageTransitionControl' is there to support multiple animations and so on... Anyway, among all of the user controls, i have a preety havy uc called ucBanks. before it shows, the ucBanks load a lot of data, manipulating it and display it on a very beautiful and smart charts. the problem is it takes some time to load it, approximately 6-7 seconds so i need the UI to show 'Loading' animation during that time (another user control called 'ucSpinner').
I'm Trying to load the ucBanks on a different thread to avoid freezing the application and it works great: the ucSpinner is showed immidiatlly and the ucBanks is loading on the background but when i change the content of the 'pageTransitionControl' i get this error:
"The calling thread cannot access this object because a different thread owns it".
I think i tried basically everything but i must missing somthing or doing somthing wrong.
This is where it all start, the btn_click event that load ucBanks:
ShowSpinner();
Thread.Sleep(100);
Thread newThread = new Thread(new ThreadStart(LoadUc));
newThread.SetApartmentState(ApartmentState.STA);
newThread.IsBackground = true;
newThread.Start();
This is the ShowSpinner method:
private void ShowSpinner()
{
ucSpinner.Opacity = 1;
}
and this is the LoadUc method:
private void LoadUc()
{
ucOsh ucOshx = new ucOsh();
Utils.LoadUc(ucOshx, null, PageTransitions.PageTransitionType.GrowAndFade, true, this, null, true);
}
With the LoadUc i called static class called 'Utils' holding the 'LoadUc' method:
public static void LoadUc(System.Windows.Controls.UserControl ucParent, System.Windows.Controls.UserControl ucChild, PageTransitions.PageTransitionType tranType, bool removeChildrens = true, System.Windows.Window w = null, List<Plist.Plist> lst = null, bool hideMenu = false)
{
MainWindow win = null;
if (w != null) { win = (MainWindow)w; }
else { win = (MainWindow)System.Windows.Window.GetWindow(ucChild); }
win.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.ContextIdle, (System.Action)delegate
{
win.pageTransitionControl.TransitionType = tranType;
win.pageTransitionControl.PARAMS = lst;
win.pageTransitionControl.Tag = ucParent.ToString();
win.pageTransitionControl.pages.Push(ucParent);
win.pageTransitionControl.Content = ucParent; ----------->>>>This is where i get the error!!!
});
}
I understand that the main window is locked inside another thread but i cant see any other option to load it without freezing the entire app.
Does anyone have a suloution to my problem? SA :-) ?
What I have tried:
i tried working with background-worker, i chaned all of the settings of the dispatcher, loaded the user control inside and outside the threads...
I have a structural problem resulting in an System.ObjectDisposedException with a dll.
More specifically it's a µEye Camera driver that is advised to capture data from a camera. I got two events from this camera that are fired asynchronously:
OnFrameEvent
OnSequenceEvent
The latter tells me that my capture is beeing completed and I can continue in saving my images.
This is the code that does the work:
private void onSequenceEvent(object sender, EventArgs e)
{
uEye.Camera Camera = sender as uEye.Camera;
SequenceCount++;
Camera.Acquisition.Stop();
int s32SeqID;
statusRet = Camera.Memory.Sequence.GetLast(out s32SeqID);
Invoke((MethodInvoker)delegate ()
{
lblStatus.Text = "Save Images...";
this.pbCapture.Value = 0;
});
Rectangle src = new Rectangle();
Rectangle dst = new Rectangle();
src.X = AOI_Size.X;
src.Y = AOI_Size.Y;
src.Width = AOI_Size.Width;
src.Height = AOI_Size.Height;
dst.X = 0; dst.Y = 0; dst.Width = AOI_Size.Width; dst.Height = AOI_Size.Height;
Bitmap bitmap_source = new Bitmap(MySensorInfo.MaxSize.Width, MySensorInfo.MaxSize.Height);;
Bitmap bitmap_destination = new Bitmap(dst.Width, dst.Height);;
Graphics g = Graphics.FromImage(bitmap_destination);
for (int i = 1; i < s32SeqID; i++)
{
Camera.Memory.ToBitmap(i, out bitmap_source);
g.DrawImage(bitmap_source, dst, src, GraphicsUnit.Pixel);
bitmap_destination.Save(PathToSave + i.ToString() + ".bmp");
this?.Invoke((MethodInvoker)delegate ()
{
pbOverallProgress.Value++;
pbCapture.Value++;
});
}
bitmap_source.Dispose();
g.Dispose();
this.CloseForm?.Invoke(1);
}
However - as you may expect the Invoke call will cause the ObjectDisposedException as the "Cancel"-Button is beeing pressed:
this?.Invoke((MethodInvoker)delegate ()
{
pbOverallProgress.Value++;
pbCapture.Value++;
});
Here's the code of the Cancel-Button:
private void btn_Exit_Click(object sender, EventArgs e)
{
if (MessageBox.Show("Do you really want to cancel?", "Abort", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
this.CloseForm?.Invoke(0);
}
}
private void UEye_Dialog_Form_CloseForm(int exitCode)
{
this?.Invoke((MethodInvoker)delegate ()
{
if (Camera != null)
{
Camera.EventFrame -= onFrameEvent;
Camera.EventSequence -= onSequenceEvent;
}
Camera?.Acquisition.Stop();
Camera = null;
ReturnCode = exitCode;
this.Close();
});
}
UEye_Dialog_Form_CloseForm(int exitCode) is a event where CloseForm is it's delegate.
I hope this was not too much information :)
This exception only occure if the image is beeing saved, not if I'm waiting for the sequence to be captured.
Sure I could pack the UI Update code within a try-catch-block or check if the forms state is Disposed/Disposing. But for my little programming skills it looks like a structural problem.
Thank you for your help :)
The tricky part is that you're doing multi-threading without synchronization.
Invoke presents one such synchronization point, which is fine. However, as you've found out, it doesn't work after the handle is disposed - this makes perfect sense; Invoke simply sends a window message to the given handle, and when the handle no longer exists there's noöne to deal with the message (not to mention what would Close (which just sends WM_CLOSE etc.) do when the window no longer exists).
Solving this is quite tricky, actually. Even if you check if the form is disposed before trying the Invoke, it might still be disposed between the check and the Invoke itself. locking would allow you to handle the synchronization, but you'd need to lock in DestroyHandle or perhaps an event like Closing - the key is to make sure that whatever signal you send is safely tied to whether Invoke is safe right now. Of course, you don't really want to use Invoke - you need BeginInvoke, otherwise you're guaranteed to have a deadlock when Invoke needs to wait for the UI thread which is currently waiting for the lock to be released. Not good :)
Being prepared for an ObjectDisposedException might be the best solution. But looking through the reference source code, it doesn't look like it's 100% correct either - it's consistent on a single thread, but you're not calling Invoke on the UI thread (obviously).
I have an Internet radio app that uses BackgroundAudioPlayer.
I need a timer in the Audio Playback Agent that will update the track title of the currently playing track of the BAP that is pulled from the Internet radio station's API.
Adding a DispatcherTimer into the Audio Playback Agent gives me a cross-thread exception, and using:
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// Code
});
Didn't work.
I need the code in here because if I put the update code in the app itself, when the user navigates away from the app the updates stop (much unlike Windows 8's behavior).
I can't use Scheduled Agents since they only run once every 30 minutes (IIRC).
Is this possible or can this not be done on Windows Phone?
Below is an excerpt from the MSDN documentation for Background Audio Player:
Sending messages between tasks:
There are times when you will want to communicate between the two processes of a background audio app. For example, you might want the background task to notify the foreground task when a new track starts playing, and then send the new song title to the foreground task to display on the screen. A simple communication mechanism raises events in both the foreground and background processes. The SendMessageToForeground and SendMessageToBackground methods each invoke events in the corresponding task. Data can be passed as an argument to the event handler in the receiving task. Pass data using a new class called ValueSet. This class is a dictionary that contains a string as a key and other value types as values. You can pass simple value types such as int, string, bool, and so on.
https://msdn.microsoft.com/en-US/library/windows/apps/xaml/dn642090
Hope this helps!
I found a question which could help you : How to run a timer on background in windows phone 8?
when you set a timer which is checking every x seconds if the "title" differs from last known title then you could send this info back to it.
This could be the Code for the Timer:
Declare these:
string _newValue = string.Empty;
string _currentValue = string.Empty;
AudioTrack _tempTrack = null;
and set this as Tick for the Timer
if (this.BackgroundAudioPlayer != null)
{
if (this.BackgroundAudioPlayer.Instance != null)
{
if (this.BackgroundAudioPlayer.Instance.Track != null)
{
this._newValue= yourAPI.GetTitleOfTrack();
try
{
/* First try to get the current Track as own Var */
this._tempTrack = this.BackgroundAudioPlayer.Instance.Track;
if (this._tempTrack != null)
{
/* Then Read the .Tag Value from it, save to _currentValue */
if (this._tempTrack.Tag != null)
{ this._currentValue = this._tempTrack.Tag.ToString(); }
else
{ this._currentValue = string.Empty; }
/* Compare */
if (this._currentValue != this._newValue)
{
/* Edit the Track Tag from your original BAP */
this.BackgroundAudioPlayer.Instance.Track.Tag = this._newValue;
}
}
}
catch(Exception ex)
{
/* if something Crashes you can save the exception error for protocol */
}
}
}
}
Remember: Change "yourAPI.GetTitleOfTrack()"-Function from this with real Function Call of your API.
Have you considered updating the information in the background audio player agent as below in the track tag.
string newTag = "whatever you need to show";
AudioTrack track = BackgroundAudioPlayer.Instance.Track;
track.BeginEdit();
track.Tag = newTag;
track.EndEdit();
and then reading that tag in the front end by your application when needed?
I currently have an application I'm writing in c# (using .NET) that requires me to start a timer as soon as a user sees an image on screen up until they respond with a key press.
Now I realise that practically this is very difficult given the monitor input lag and response time, the time the keyboard takes to physically send the message, the OS to process it, etc.
But I'm trying my best to reduce it down to mostly a constant error (the response time results will be used to compare one user to the next so a constant error isn't really an issue). However annoying hurdle is the variable caused by the monitor refresh rate, as I gather when my onPaint message is called and done with, it doesn't mean the image has actually been processed and sent from the graphics buffer?
Unfortunately time restrictions and other commitments would realistically restrict me to continuing this task in c# for windows.
So what I was wondering was if either handling all the drawing in OpenGL or DirectX or better still for me if it is possible to just using either OpenGL or DirectX to create an event when the screen is updated?
Another suggestion given to me previously was regarding V-Sync, if I switch this off is the image sent as soon as it is drawn? as opposed to sending images at a set rate synchronised to the monitor refresh rate?
You must render your graphic in a separate thread in order to:
Use vertical synchronisation to have a precise timing of the effective display of your image.
Get the precise timing of your user input (since user interface is not on the same thread than the render loop.
Initialise Direct3D to enable the VSync during render :
// DirectX example
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferCount = 1;
presentParams.PresentationInterval = PresentInterval.One;
device = new Device(...
Perform the render in a separate thread:
Thread renderThread = new Thread(RenderLoop);
renderThread.Start();
shouldDisplayImageEvent = new AutoResetEvent();
Then use the following render loop:
void RenderLoop()
{
while(applicationActive)
{
device.BeginScene();
// Other rendering task
if (shouldDisplayImageEvent.WaitOne(0))
{
// Render image
// ...
userResponseStopwatch = new Stopwatch();
userResponseStopwatch.Start();
}
device.EndScene();
device.Present();
}
}
Then handle the user input :
void OnUserInput(object sender, EventArgs e)
{
if (userResponseStopwatch != null)
{
userResponseStopwatch.Stop();
float userResponseDuration = userResponseStopwatch.ElapsedMillisecond - 1000 / device.DisplayMode.RefreshRate - displayDeviceDelayConstant;
userResponseStopwatch = null;
}
}
You now use the shouldDisplayImageEvent.Set() event trigger to display the image as needed and start the stop watch.
First enable the VSync on your application idle loop :
// DirectX example
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.BackBufferCount = 1;
presentParams.PresentationInterval = PresentInterval.One;
device = new Device(...
Application.Idle += new EventHandler(OnApplicationIdle);
// More on this here : http://blogs.msdn.com/tmiller/archive/2005/05/05/415008.aspx
internal void OnApplicationIdle(object sender, EventArgs e)
{
Msg msg = new Msg();
while (true)
{
if (PeekMessage(out msg, IntPtr.Zero, 0, 0, 0))
break;
}
// Clearing render
// ...
if (displayImage)
{
// Render image
// ...
renderTime = DateTime.now();
}
device.Present();
}
With the vsync enabled, the device.Present function block until the next frame synchronisation, so if you compute the time between renderTime and the user input time and remove the display device delay + 16.67ms you should get your user response delay.