How to Poll For Controller Input In UWP App - events

I'm unsure about the best practice for obtaining and updating input received from a controller monitored using the GamePad class in UWP.
I've seen a couple of examples of people using Dispatch Timers and async loops inside the GamePadAdded event. In Win32 applications, I would have handled input in the WinMain update/message loop, but in UWP apps I don't know of anything similar.
Is there a loop in UWP apps that input should be collected/handled like in Win32 apps? What is the recommended protocol for polling for input from a input device (nominally a Xbox One controller)?
I'm happy to read more about UWP app development but I'm unsure of any guides that reference something like this.
Edit: It would be productive if, instead of downvoting and moving on, you shared thoughts on why this question deserved a downvote.

I've seen a couple of examples of people using Dispatch Timers and async loops inside the GamePadAdded event
This is the right way in UWP app to read Gamepad data. A little suggestion is, move the loop reading part on UI thread if you need to update UI frequently. See the solution in this blog
Is there a loop in UWP apps that input should be collected/handled like in Win32 apps
You may make a wrapper with custom event, see the open source implementation: XBoxGamepad
public class XBoxGamepad
{
private List<Gamepad> _controllers = new List<Gamepad>();
private bool _running = true;
Task backgroundWorkTask;
public event EventHandler<GamepadButtons> OnXBoxGamepadButtonPressA;
//omitted......
public XBoxGamepad()
{
Gamepad.GamepadAdded += Gamepad_GamepadAdded;
Gamepad.GamepadRemoved += Gamepad_GamepadRemoved;
backgroundWorkTask = Task.Run(() => PollGamepad());
}
//omitted......
private void Start()
{
_running = true;
}
public void Stop()
{
_running = false;
}
public async Task PollGamepad()
{
while (true)
{
if (_running)
{
foreach (Gamepad controller in _controllers)
{
if (controller.GetCurrentReading().Buttons == GamepadButtons.A)
{
OnXBoxGamepadButtonPressA(controller, controller.GetCurrentReading().Buttons);
}
//omitted......
}
}
await Task.Delay(50);
}
}
private void Gamepad_GamepadRemoved(object sender, Gamepad e)
{
_controllers.Remove(e);
}
private void Gamepad_GamepadAdded(object sender, Gamepad e)
{
_controllers.Add(e);
}
}

Related

How to create a never ending background service in Xamarin.Forms?

I am monitoring the user's location every 15 minutes and I just want the application to continue sending the location even if the user closes the application in the taskbar.
I tried this sample but it's in Xamarin.Android https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/services/foreground-services i have to create a dependencyservice but i don't know how.
i have to create a dependencyservice but i don't know how.
First, create an Interface in the Xamarin.forms project:
public interface IStartService
{
void StartForegroundServiceCompat();
}
And then create a new file let's call it itstartServiceAndroid in xxx.Android project to implement the service you want:
[assembly: Dependency(typeof(startServiceAndroid))]
namespace DependencyServiceDemos.Droid
{
public class startServiceAndroid : IStartService
{
public void StartForegroundServiceCompat()
{
var intent = new Intent(MainActivity.Instance, typeof(myLocationService));
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
MainActivity.Instance.StartForegroundService(intent);
}
else
{
MainActivity.Instance.StartService(intent);
}
}
}
[Service]
public class myLocationService : Service
{
public override IBinder OnBind(Intent intent)
{
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
// Code not directly related to publishing the notification has been omitted for clarity.
// Normally, this method would hold the code to be run when the service is started.
//Write want you want to do here
}
}
}
Once you want to call the StartForegroundServiceCompat method in Xamarin.forms project, you can use:
public MainPage()
{
InitializeComponent();
//call method to start service, you can put this line everywhere you want to get start
DependencyService.Get<IStartService>().StartForegroundServiceCompat();
}
Here is the document about dependency-service
For iOS, if the user closes the application in the taskbar, you will no longer be able to run any service. If the app is running, you can read this document about ios-backgrounding-walkthroughs/location-walkthrough
You might want to have a look at Shiny by Allan Ritchie. It's currently in beta but I would still suggest using it, as it will save you a lot of trouble writing this code yourself. Here's a blog post by Allan, explaining what you can do with Shiny in terms of background tasks - I think Scheduled Jobs are the thing you're looking for.

How to use CXCallObserver in Xamarin?

I need to subscribe an event to handle incoming phone call. Since iOS version 11.0 CTCallCenter is deprecated we have to use CXCallObserver. I successfully implemented solution for CTCallCenter, but I am not able to subscribe event for CXCallObserver. Does anyone have working solution for CXCallObserver?
Here is my code to subscribe event for CTCallCenter..
_callCenter = new CTCallCenter();
_callCenter.CallEventHandler += CallEvent;
private void CallEvent(CTCall call)
{
CoreFoundation.DispatchQueue.MainQueue.DispatchSync(() =>
{
if(call.CallState.Equals(call.StateIncoming))
//Do something
});
}
Implement the delegate for CXCallObserver:
public class MyCXCallObserverDelegate : CXCallObserverDelegate
{
public override void CallChanged(CXCallObserver callObserver, CXCall call)
{
Console.WriteLine(call);
}
}
Then in your code, create a instance of CXCallObserver (maintain a strong reference to this) and then assign the delegate:
cXCallObserver = new CXCallObserver();
cXCallObserver.SetDelegate(new MyCXCallObserverDelegate(), null);

How to use async method in DelegateCommand

I want to link async method to a delegate command in prism framework in Xamarin.Forms and my question is how to do it?
Is below solution correct? Is there exist any pitfall? (deadlock, UI slow or freezing, bad practices, ...)
{ // My view model constructor
...
MyCommand = new DelegateCommand(async () => await MyJobAsync());
...
}
private async Task MyJobAsync()
{
... // Some await calls
... // Some UI element changed such as binded Observable collections
}
You can use async void directly. However, a few notes from my experience...
The structure of your code is: start asynchronous operation and then update UI with the results. This implies to me that you would be better served with a NotifyTask<T> kind of approach to asynchronous data binding, not commands. See my async MVVM data binding article for more about the design behind NotifyTask<T> (but note that the latest code has a bugfix and other enhancements).
If you really do need an asynchronous command (which is much more rare), you can use async void directly or build an async command type as I describe in my article on async MVVM commmands. I also have types to support this but the APIs for these are more in flux.
If you do choose to use async void directly:
Consider making your async Task logic public, or at least accessible to your unit tests.
Don't forget to handle exceptions properly. Just like a plain DelegateTask, any exceptions from your delegate must be properly handled.
Just have a look at this link if you're using Prism Library: https://prismlibrary.com/docs/commands/commanding.html#implementing-a-task-based-delegatecommand
In case you want to pass a CommandParameter to DelegateCommand, use in the DelegateCommand variable declaration this syntax
public DelegateCommand<object> MyCommand { get; set; }
In the constructor of the ViewModel initialize it this way:
MyCommand = new DelegateCommand<object>(HandleTap);
where HandleTap is declared as
private async void HandleTap(object param)
Hope it helps.
As has already been mentioned the way to handle async code with delegate command is to use async void. There has been a lot of discussion on this, far beyond just Prism or Xamarin Forms. The bottom line is that ICommand that both the Xamarin Forms Command and Prism DelegateCommand are limited by ICommand's void Execute(object obj). If you'd like to get more information on this I would encourage you to read the blog by Brian Lagunas explaining why DelegateCommand.FromAsync handler is obsolete.
Generally most concerns are handled very easily by updating the code. For example. I often hear complaints about Exceptions as "the reason" why FromAsync was necessary, only to see in their code they never had a try catch. Because async void is fire and forget, another complaint I've heard is that a command could execute twice. That also is easily fixed with DelegateCommands ObservesProperty and ObservesCanExecute.
I think the two main problems when calling an asynchronous method from one that executes synchronously (ICommand.Execute) are 1) denying to execute again while previous call is still running 2) handling of exceptions. Both can be tackled with an implementation like the following (prototype). This would be an async replacement for the DelegateCommand.
public sealed class AsyncDelegateCommand : ICommand
{
private readonly Func<object, Task> func;
private readonly Action<Exception> faultHandlerAction;
private int callRunning = 0;
// Pass in the async delegate (which takes an object parameter and returns a Task)
// and a delegate which handles exceptions
public AsyncDelegateCommand(Func<object, Task> func, Action<Exception> faultHandlerAction)
{
this.func = func;
this.faultHandlerAction = faultHandlerAction;
}
public bool CanExecute(object parameter)
{
return callRunning == 0;
}
public void Execute(object parameter)
{
// Replace value of callRunning with 1 if 0, otherwise return - (if already 1).
// This ensures that there is only one running call at a time.
if (Interlocked.CompareExchange(ref callRunning, 1, 0) == 1)
{
return;
}
OnCanExecuteChanged();
func(parameter).ContinueWith((task, _) => ExecuteFinished(task), null, TaskContinuationOptions.ExecuteSynchronously);
}
private void ExecuteFinished(Task task)
{
// Replace value of callRunning with 0
Interlocked.Exchange(ref callRunning, 0);
// Call error handling if task has faulted
if (task.IsFaulted)
{
faultHandlerAction(task.Exception);
}
OnCanExecuteChanged();
}
public event EventHandler CanExecuteChanged;
private void OnCanExecuteChanged()
{
// Raising this event tells for example a button to display itself as "grayed out" while async operation is still running
var handler = CanExecuteChanged;
if (handler != null) handler(this, EventArgs.Empty);
}
}
async void
I personally would avoid "async void" at all cost. It is impossible to know from the outside when the operation has finished and error handling becomes tricky. In regards to latter, for instance writing an "async Task" method which is called from an "async void" method almost needs to be aware of how its failing Task is propagated:
public async Task SomeLogic()
{
var success = await SomeFurtherLogic();
if (!success)
{
throw new DomainException(..); // Normal thing to do
}
}
And then someone writing on a different day:
public async void CommandHandler()
{
await SomeLogic(); // Calling a method. Normal thing to do but can lead to an unobserved Task exception
}
Is UI thread running DelegateCommand and background threads running await expression?
Yes, the UI thread runs the DelegateCommand. In case of an async one, it runs until the first await statement, and then resumes his regular UI thread work. If the awaiter is configured to capture the synchronization context (that is, you do not use .ConfigureAwait(false)) the UI thread will continue to run the DelegateCommand after the await.
Is UI thread running DelegateCommand and background threads running await expression?
Whether the "await expression" runs on a background thread, foreground thread, a threadpool thread or whatever depends on the api you call. For example, you can push cpu-bound work to the threadpool using Task.Run or you can wait for an i/o-operation without using any thread at all with methods like Stream.ReadAsync
public ICommand MyCommand{get;set;}
//constructor
public ctor()
{
MyCommand = new Xamarin.Forms.Command(CmdDoTheJob);
}
public async void DoTheJob()
{
await TheMethod();
}
public DelegateCommand MyCommand => new DelegateCommand(MyMethod);
private async void MyMethod()
{
}
There are no pitfalls. A void return type in async method was created especially for delegates. If you want to change something, that has reflected on UI, insert relevant code in this block:
Device.BeginOnMainThread(()=>
{
your code;
});
Actually, ICommand and DelegateCommand pretty similar, so an above answer is quite right.

Multiple c# SerialPorts seems to hang my application

I've an application in Windows forms that connects to 16 serialports. The structure I used for each one is:
private void Serial_CodeNip_15_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string S = Serial_CodeNip_15.ReadExisting();
myProcess(S);
}
public delegate void del_myProcess(string stringa);
private void myProcess(string stringa)
{
if (this.InvokeRequired)
{
del_myProcess tmp = new del_myProcess(myProcess);
try
{
this.Invoke(tmp, stringa);
}
catch (Exception)
{
}
}
else
{
// my code here
}
}
Receiving data from barcode readers, works fine until more Readers (up 6 or 7) start reading at the same time. In this cases my application tends to hang and all readers denotes a difficult to catch data from serial input buffers. Is this the correct way to read async data from serialports or there’s another simple way to do that. I noticed that working with few serialports there’s no problem.
Thank you in advance for helping

Outlook Folder events randomly stop working on Shared Mailbox

I'm working on a WPF application that monitors numerous folders in an Outlook Shared Mailbox. I have wired up ItemAdd and ItemRemove event handlers to a Folder.Items object.
Everything works great for a few minutes. But as time goes on, the event handling seems to go "poof". Some folders will still recognize add and remove, others will only see removes, while others are blind to any activity. To me it seems like the event handlers are being garbage collected, but my Items object IS declared as a global variable in the class it sits in, so I don't see how they could be GC'd out.
Are there any pitfalls I should be aware of with Outlook Folder.Items events? I have a previous, simpler application that works by similar processes that works fine for extended periods of time. There is no intrinsic difference, as far as Item event handling goes, between my old app and this new one. I'm really at a loss as to what's causing this.
Below is the relevant code. To bring some context to this, what I'm doing is, for each Folder in the Outlook Shared Mailbox a "TicketView" UserControl is created which represents the contents (MailItems) of that folder. This TicketView is a simple ListBox that may contain between 0 to a couple dozen MailItems -- nothing excessive.
public partial class TicketView : UserControl
{
private Folder _thisFolder = null;
private TicketCollection _thisTicketColl = null;
private Items _thisItems = null;
public TicketView(Folder folder)
{
InitializeComponent();
_thisTicketColl = this.FindResource("TicketCollection") as TicketCollection;
_thisFolder = folder;
_thisItems = folder.Items;
SetFolderEvents();
Refresh();
}
private void SetFolderEvents()
{
_thisItems.ItemAdd += new ItemsEvents_ItemAddEventHandler(delegate
{
Refresh();
});
_thisItems.ItemRemove += new ItemsEvents_ItemRemoveEventHandler(delegate
{
Refresh();
});
}
public void Refresh()
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(delegate(object sender, DoWorkEventArgs e)
{
string[] fields = new string[] { "Subject", "SenderName", "SentOn", "EntryID" };
var olTable = TicketMonitorStatics.GetOutlookTable(_thisFolder, fields, filter);
olTable.Sort("SentOn", true);
var refreshedList = new List<Ticket>();
while (!olTable.EndOfTable)
{
var olRow = olTable.GetNextRow();
refreshedList.Add(new Ticket
{
Subject = olRow["Subject"],
Sender = olRow["SenderName"],
SentOn = olRow["SentOn"],
EntryID = olRow["EntryID"]
});
};
e.Result = refreshedList;
});
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(delegate(object sender, RunWorkerCompletedEventArgs e)
{
var refreshedList = e.Result as List<Ticket>;
UpdateTicketList(refreshedList);
worker.Dispose();
});
worker.RunWorkerAsync();
}
private void UpdateTicketList(List<Ticket> newList)
{
_thisTicketColl.Clear();
foreach (Ticket t in newList)
{
_thisTicketColl.Add(t);
}
}
}
}
Outlook events should not be used for any kind of synchronization. They are designed to be used for the UI purposes only and can be dropped under heavy loads or if a network error occurs (if you are using an online store).
You can use events only as a hint that your code needs to run sooner rather than later.
You can use the IExchangeExportChanges MAPI interface (C++ or Delphi only) to perform synchronization; this is the same API used by Outlook to synchronize its cached folders. If you are not using C++ or Delphi, you can use Redemption (I am its author) and its RDOFolderSynchronizer object.

Resources