In a Windows 8 app (C#) using the MediaCapture class (Windows.Media.Capture) to show a webcam feed, I'm trying to restart the preview when the app has lost and then come back into focus (e.g. by clicking in the top left screen corner to another app, then clicking again to come back to my app).
How I'm trying to restart the preview right now is:
Application.Current.Resuming += (sender, o) => StartVideo(video);
Application.Current.Suspending += (sender, args) => StopVideo();
internal async void StartVideo(CaptureElement e)
{
try
{
this.stream = new MediaCapture();
await this.stream.InitializeAsync();
e.Source = this.stream;
await this.stream.StartPreviewAsync();
}
catch
{
new MessageDialog("Unable to start the video capture.").ShowAsync();
}
}
internal async void StopVideo()
{
try
{
await stream.StopPreviewAsync();
}
catch { }
}
But, the Resuming and Suspending events don't seem to fire in the example I describe above. Is this not "suspending" an app? If so, what is it/what events should I be on the lookout for?
Alternatively, should I, instead of using a long-running "preview" to display the webcam, use one of the this.stream.StartRecord... methods?
EDIT: If I fire the events manually using Visual Studio's Suspend/Resume button (on the Debug Location toolbar), the functionality works as desired (the video restarts when the app is resumed).
I see a few things wrong:
You should avoid async void; use async Task for all methods except event handlers.
For "command" events such as Suspending, use the deferral provided by args.SuspendingOperation.GetDeferral if you have an async event handler.
Related
I am trying to have some logic when Windows user is being changed while my UWP app is running and for that in my OnLaunchApplicationAsync method I have:
var userWatcher = Windows.System.User.CreateWatcher();
userWatcher.AuthenticationStatusChanged += AuthenticationStatusChanged;
and I also have
private void AuthenticationStatusChanged(Windows.System.UserWatcher sender, Windows.System.UserChangedEventArgs args)
{
// Some logic
}
But the problem is that when I log off with my current user and sign in with another one, the expected event is not being raised.
I have also tried out userWatcher.Updated for updating user data as well as userWatcher.AuthenticationStatusChanging with the same result.
Am I doing this in a wrong way?
You need to start the watcher, otherwise these events are not fired.
I have a background agent for my windows phone 8.1(C#) which listens to push notifications.
I also have a foreground App and it handles push notification if it is running.
The problem is that the background agent invokes a custom method await SyncPushChanges.initUpdate(true); several times causing duplicate values in my sqlite database.
Here is code for foreground delegate:
static async void channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args)
{
//Init update from the server
await SyncPushChanges.initUpdate();
//Prevent background agentt from being invoked
args.Cancel = true;
}
Code In background Agent
public async void Run(IBackgroundTaskInstance taskInstance)
{
var deferal = taskInstance.GetDeferral();//Save on CPU seconds since we are doing async
//Get the token and invoke get new data
await SyncPushChanges.initUpdate(true);
deferal.Complete();
}
Anyone who might know why am having my method invokes many times?Your help will be highly appreciated
I found a solution myself.
The issue was that I was not unregistering my background agent and this caused it to work incorrectly when the app was updated(In this case when I run the application again from VS2013).
The following code did the magic
BackgroundExecutionManager.RemoveAccess();
//Unregister the Background Agent
var entry = BackgroundTaskRegistration.AllTasks.FirstOrDefault(keyval => keyval.Value.Name == "myAgent");
if (entry.Value != null)
{
entry.Value.Unregister(true);
}
I'm starting out in C#, coded a lot in Java but having some trouble here. I'm trying to learn how to use MouseKeyHook for an application I'm developing. I cannot get the actual listener to fire off an event. Here's my listener code:
using System;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;
namespace ChromaHeatmap
{
class keyListener
{
private IKeyboardMouseEvents m_GlobalHook;
public void Subscribe()
{
// Note: for the application hook, use the Hook.AppEvents() instead
m_GlobalHook = Hook.GlobalEvents();
m_GlobalHook.KeyPress += GlobalHookKeyPress;
}
private void GlobalHookKeyPress(object sender, KeyPressEventArgs e)
{
Console.WriteLine("blah");
}
public void Unsubscribe()
{
m_GlobalHook.KeyPress -= GlobalHookKeyPress;
//It is recommened to dispose it
m_GlobalHook.Dispose();
}
}
}
And here's the part of my application code where I attempt to do something with the listener. If anyone can let me know what the best way is to loop here and wait for events, I'd appreciate it.
//Listen for key presses
keyListener heyListen = new keyListener();
heyListen.Subscribe();
while(true)
{
}
while(true) {}
This is a hold-and-catch-fire statement, the thread will burn 100% core and cannot execute the hook callback. You'll notice that the machine goes dead for 5 seconds when you press a key, the operating system is waiting for an opportunity to invoke the callback. But it won't wait forever and unceremoniously will destroy the hook so you regain control over the machine. Also the kind of mishap that will occur when you try to debug your event handler.
Windows needs an opportunity to safely call the hook callback. That requires your program to be "idle", not executing any code. The technical term for this is "pumping the message loop", your program must wait for a notification from the operating system that something interesting happened.
A very simple way is to use the Winforms project template as-is, you'll also get a window. Note how the Main() method in the project makes the call that you need instead of the while() loop. You must call Application.Run().
Check this post for code that avoids displaying a window.
I am creating a game in WPF. To manage sounds I've created a AudioController, which will create MediaPlayers and manage playing, stopping, looping, pausing, etc. I have the base of it working. If i'm in a control, I can call
AudioController.Play("MySound");
And it will decide if it has a MediaPlayer for that sound already, if not it will create one.
A problem appears in the following situations:
Task.Run(() => { DoSomething(); AudioController.Play("MySound"); });
_timer_tick(object sender...) { AudioController.Play("MySound"); }
When using a Task my Sound will play properly, but the MediaEnded event never gets fired, causing me not to be able to manage the MediaPlayers properly.
With the Timer Tick, the Sound will play the first time, but never again, even though its using a new MediaPlayer and also never fires the MediaEnded event
I've tried Dispatching the calls, but it doesn't seem to make a difference.
I can only imagine the problems lies with the idea that the Play() call is being sent from a different thread.
public static void Play(string sound)
{
Debug.WriteLine("Publish called on Thread Id {0}", Thread.CurrentThread.ManagedThreadId);
if (!Application.Current.CheckAccess())
{
Application.Current.Dispatcher.Invoke(() => Play(sound, TimeSpan.Zero), DispatcherPriority.Normal);
return;
}
Play(sound, TimeSpan.Zero);
}
private static void Play(string sound, TimeSpan position)
{
//...some preemptive code that's just searching a list
//reuse
if (ap == null)
{
ap = new AudioPlayer(entry);
_players.Add(ap);
}
ap.Play(position);
}
Note: AudioPlayer is a wrapper class around MediaPlayer so that I can add some additional properties such as LastActive, IsLooping, and handles replaying a sound by calling:
_player.Stop();
_player.Position = position;
_player.Play();
Update:
I just decided to run a different sound in the above scenario's and everything seems to work fine. The only difference between the audio's is that one is 40kb and the other 67kb. Could it be that the file is just so small MediaPlayer doesn't register the NaturalDuration and therefore assumes its 0 which stops the events from being triggered?
We have an application that has a primary window, it can launch multiple other windows, in new browsers. We are using a silverlight application as a coordinating server in the primary window to close all windows that are part of the app, regardless of the way they are opened (we can't guarantee it was via window.open so don't always have a handle to the window in javascript).
On log out, we want to signal all the other windows to perform an auto-save, if necessary, then close down.
So all windows have a silverlight app, they coordinate using localmessagesenders. However, these are asynchronous:
private void ProcessAutosave()
{
foreach (string s in _windows)
{
SendMessage(s, "notify-logout");
}
// code here quoted later...
}
// sendasynch doesn't send until the method terminates, so have to do it in it's own function.
private void SendMessage(string to, string message)
{
var lms = new LocalMessageSender(to);
lms.SendCompleted += new EventHandler<SendCompletedEventArgs>(SenderSendCompleted);
lms.SendAsync(message);
}
Since the ProcessAutosave is called from a javascript onunload event which can't be cancelled, we need this to be synchronous and not complete before we have a response processed from each sub-window so the session state will still be valid etc.
In the SenderSendCompleted we remove items from _windows when they have said they're done.
So I added a loop on the end:
while(_windows.Count > 0) {
Thread.Sleep(1)
}
However, that never terminates, unless I put an iteration counter on it.
Am I the victim of a compiler optimisation meaning the changes in SenderSendCompleted do not affect that while loop, or, have I fundamentally misunderstood something? Or missed something obvious that's staring me in the face?
It sounds like a subtle verson of a race situation due to going sync/async. Couldn't the process in queston also receive notifications from the windows that they have received the message and are shutting down? Once all of the counter messages have been received, then the main app could shut down without the busy wait at the end(?).
I have found a way to work round. However, this does not really "solve" the problem generally, just in my case, which is also only supporting internet explorer.
function WindowCloseEventHandler()
{
var app = // get silverlight app handle...
app.doAutoSave();
var params = 'whatever you need';
var args = new Object();
args.hwnd = window;
window.showModalDialog('blocker.aspx',args,params);
}
function checkAutoSave()
{
var app = // get silverlight app handle...
return app.autosavecomplete();
}
Then in blocker.aspx we display a static "performing logout handlers" type message and do:
function timerTick()
{
if(window.dialogArguments.hwnd.checkAutoSave()) {
window.close();
} else {
setTimeout(timerTick, 500);
}
}
And start the timer on window load.
The child window's silverlight apps are notified to start an autosave, then they notify the parent when they are done. We then poll the parent's status from a modal dialog, which blocks the termination of the WindowCloseEventHandler() which we have wired up to the onclose event of the body.
It's hacky and horrible, but it means silverlight stays asynchronous and we're using a javascript timer so the javascript isn't loading the system.
Of course if the user closes the modal dialogue, there is a potential for issue.