Send speech recognition args.Result as parameter in UWP desktop-bridge package - c#

I'm trying to figure out, if it is possible send using Windows.Media.SpeechRecognition; args.Result.Text as parameter from UWP to Console application.
For example by following scenario I'm sending TextToSpeech(args.Result.Text); with args.Result.Text; value, where using Windows.Media.SpeechSynthesis; text-to-speech pronounces the recognition result each time when args.Result.Text; appears. textBlock2.Text = args.Result.Text; also displays result:
private async void ContinuousRecognitionSession_ResultGenerated(
SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
textBlock1.Text = args.Result.Text;
TextToSpeech(args.Result.Text);
});
}
but if I'm trying to send args.Result.Text; as parameter to console application, included with UWP in Desktop-Bridge package:
private async void ContinuousRecognitionSession_ResultGenerated(
SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
textBlock1.Text = args.Result.Text;
SendTTSResult(args.Result.Text);
});
}
to the requested function:
private async void SendTTSResult(string res)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
{
ApplicationData.Current.LocalSettings.Values["parameters"] = res;
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Parameters");
}
});
}
Behavior of failure looks to me not really clear:
With first recognition result, it sends parameter to console application, which successfully loads, gets and displays this parameter. But with second request the problem backs away from this processing level, even if parameters sending function is unambiguously the cause of a failure SendTTSResult(args.Result.Text); function does not receives args.Result.Text but this happens already before function will comes in action, because preceding output display textBlock1.Text = args.Result.Text; also does not receives event anymore.
With async() => behavior is a bit different, it successfully receives event and sends value as parameter to console, in this case it happens 2-3 times from beginning of execution and voice requesting, then event disappears, when it is not even passed through SendTTSResult(string res), to imagine that the something in SendTTSResult(string res) does not allows pass string from recognition, but just stops, even if I put it in the end of TextToSpeech(string text) function, text to speech also stops receive event:
private async void SendTTSResult(string res)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() =>
{
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
{
ApplicationData.Current.LocalSettings.Values["parameters"] = res;
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Parameters");
}
});
}
It looks like sending of args.Result.Text value as parameter with SendTTSResult(string res) function works fine, sends string successfully, but at the same time presence of this function in ContinuousRecognitionSession_ResultGenerated somehow affects receiving of event inside of it. At the same time behavior of ContSpeechRecognizer_HypothesisGenerated looks completely different, args.Hypothesis.Text event appears each time and result successfully passes as parameter with same SendTTSResult(string res).
What can prevent an event from being executed when the function of sending a parameter is involved in its process, and how to fix it if possible?
Full code of continuous speech recognition added to my question on Windows Dev Center Send speech recognition args.Result as parameter in UWP desktop-bridge package
EDIT 1: **************************************************************************************************
Behind parameter function, Console Connector.exe only shows parameter without running of any app or anything else:
static void Main(string[] args)
{
string result = Assembly.GetExecutingAssembly().Location;
int index = result.LastIndexOf("\\");
string rootPath = $"{result.Substring(0, index)}\\..\\";
if (args.Length > 2)
{
switch (args[2])
{
case "/parameters":
string parameters = ApplicationData.Current.LocalSettings.Values["parameters"] as string;
Console.WriteLine("Parameter: " + parameters);
Console.ReadLine();
break;
}
}
}
Packeage.appxmanifest:
<uap:Extension Category="windows.appService">
<uap:AppService Name="SampleInteropService" />
</uap:Extension>
<desktop:Extension Category="windows.fullTrustProcess" Executable="Connector\Connector.exe">
<desktop:FullTrustProcess>
<desktop:ParameterGroup GroupId="Parameters" Parameters="/parameters" />
</desktop:FullTrustProcess>
</desktop:Extension>
EDIT 2: **************************************************************************************************
I've tried SendTTSResult(SpeechRecogVal); with change of variable value:
private async void ContinuousRecognitionSession_ResultGenerated(
SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
SpeechRecogVal = args.Result.Text;
});
}
but it is same behavior tbRec.Text = SpeechRecogVal; shows output successfully until I add SendTTSResult(SpeechRecogVal);,
private string _srVal;
public string SpeechRecogVal
{
get
{
return _srVal;
}
set
{
_srVal = value;
ValueChanged();
}
}
void ValueChanged()
{
tbRec.Text = SpeechRecogVal;
// SendTTSResult(SpeechRecogVal);
}
So, seems like problem is something between await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => and if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0)) and await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => of private async voidContinuousRecognitionSession_ResultGenerated(SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
Also, I've tried:
private async void ContinuousRecognitionSession_ResultGenerated(
SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
{
await SendTTSResult(args.Result.Text);
}
as Task:
async Task SendTTSResult(string res)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
{
ApplicationData.Current.LocalSettings.Values["parameters"] = res;
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Parameters");
}
});
}
And it is also successful only with first request event instance response, then goes quite. So seems like ContinuousRecognitionSession_ResultGenerated is someway different from other options in Windows.Media.SpeechRecognition Namespace and not compatible with something in async Task SendTTSResult(string res) or rather with this code lines content:
ApplicationData.Current.LocalSettings.Values["parameters"] = args.Result.Text;
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Parameters");

System.NullReferenceException occurs appservice disconnect scenario, Could you check the apservice's connection before send message?
For explain this, I create sample project that refer Stefanwick blog. And I also reproduce your issue when I does not invoke InitializeAppServiceConnection method in WPF client. If you want to send text to wpf, you could invoke Connection.SendMessageAsync method just like below SendMesssage click envent .
Capability
<Extensions>
<uap:Extension Category="windows.appService">
<uap:AppService Name="SampleInteropService" />
</uap:Extension>
<desktop:Extension Category="windows.fullTrustProcess" Executable="AlertWindow\AlertWindow.exe" />
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
</Capabilities>
WPF
private AppServiceConnection connection = null;
public MainWindow()
{
InitializeComponent();
InitializeAppServiceConnection();
}
private async void InitializeAppServiceConnection()
{
connection = new AppServiceConnection();
connection.AppServiceName = "SampleInteropService";
connection.PackageFamilyName = Package.Current.Id.FamilyName;
connection.RequestReceived += Connection_RequestReceived;
connection.ServiceClosed += Connection_ServiceClosed;
AppServiceConnectionStatus status = await connection.OpenAsync();
if (status != AppServiceConnectionStatus.Success)
{
MessageBox.Show(status.ToString());
this.IsEnabled = false;
}
}
private void Connection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
Application.Current.Shutdown();
}));
}
private async void Connection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
// retrive the reg key name from the ValueSet in the request
string key = args.Request.Message["KEY"] as string;
if (key.Length > 0)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
InfoBlock.Text = key;
}));
ValueSet response = new ValueSet();
response.Add("OK", "SEND SUCCESS");
await args.Request.SendResponseAsync(response);
}
else
{
ValueSet response = new ValueSet();
response.Add("ERROR", "INVALID REQUEST");
await args.Request.SendResponseAsync(response);
}
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
ValueSet response = new ValueSet();
response.Add("OK", "AlerWindow Message");
await connection.SendMessageAsync(response);
}
UWP
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
{
App.AppServiceConnected += MainPage_AppServiceConnected;
App.AppServiceDisconnected += MainPage_AppServiceDisconnected;
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
}
}
private async void MainPage_AppServiceDisconnected(object sender, EventArgs e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Reconnect();
});
}
private void MainPage_AppServiceConnected(object sender, AppServiceTriggerDetails e)
{
App.Connection.RequestReceived += AppServiceConnection_RequestReceived;
}
private async void AppServiceConnection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
string value = args.Request.Message["OK"] as string;
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
InfoBlock.Text = value;
});
}
private async void Reconnect()
{
if (App.IsForeground)
{
MessageDialog dlg = new MessageDialog("Connection to desktop process lost. Reconnect?");
UICommand yesCommand = new UICommand("Yes", async (r) =>
{
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
});
dlg.Commands.Add(yesCommand);
UICommand noCommand = new UICommand("No", (r) => { });
dlg.Commands.Add(noCommand);
await dlg.ShowAsync();
}
}
private int count = 0;
private async void SendMesssage(object sender, RoutedEventArgs e)
{
count++;
ValueSet request = new ValueSet();
request.Add("KEY", $"Test{count}");
AppServiceResponse response = await App.Connection.SendMessageAsync(request);
// display the response key/value pairs
foreach (string value in response.Message.Values)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
StatusBlock.Text = value;
});
}
}
This is complete code sample.

Related

Run and Wait for async Task to complete in a Windows Form Application

How can I wait for an async task to complete without freezing the whole Application?
This function works but Cout() gets called while the File is still downloading.
private void Btn_test_Click(object sender, EventArgs e)
{
var task = Task.Run(async () => { await DownloadWebFile("https://speed.hetzner.de/100MB.bin", AppDomain.CurrentDomain.BaseDirectory + "//100MB.bin"); });
Cout(DownloadSuccessMsg);
}
when I do this the whole Application freezes:
private void Btn_test_Click(object sender, EventArgs e)
{
var task = Task.Run(async () => { await DownloadWebFile("https://speed.hetzner.de/100MB.bin", AppDomain.CurrentDomain.BaseDirectory + "//100MB.bin"); });
task.Wait();
Cout(DownloadSuccessMsg);
}
How can I wait correctly before running other code depending on the downloaded file?
private static async Task DownloadWebFile(string url, string fullPath)
{
using var client = new DownloadManager(url, fullPath);
client.ProgressChanged += (totalFileSize, totalBytesDownloaded, progressPercentage) =>
{
SetProgressBarValue((int)progressPercentage);
};
await client.StartDownload();
}
You can mark the method as async void. Returning void from an asynchronous method is usually not a great idea, but in the case of an event handler it's usually considered acceptable.
private async void Btn_test_Click(object sender, EventArgs e)
{
await DownloadWebFile("https://speed.hetzner.de/100MB.bin", AppDomain.CurrentDomain.BaseDirectory + "//100MB.bin");
Cout(DownloadSuccessMsg);
}

Async method to update ui executes partially

I'm developing an android app using xamarin and what I'm trying to do is really simple: on the click of a button disable itself for 1 second.
Here's the relevant part of the code I put together:
protected override void OnCreate(Bundle savedInstanceState)
{
//...
sendShortDataButton.Click += (object sender, EventArgs e) => {
Task.Run(() => DisableButtonFor());
};
//...
private async Task DisableButtonFor()
{
sendShortDataButton.Enabled = false; //<------
await Task.Delay(1000);
sendShortDataButton.Enabled = true;
}
}
The problem here is that, by debugging the app, the code runs only to where the arrow points everything after gets ignored. On the app the button does actually get disabled, so I'm not really sure what's going wrong.
Thanks!
Try this:
sendShortDataButton.Click += async (sender, e) =>
{
var button = (Button)sender;
button.Enabled = false;
await Task.Delay(1000);
button.Enabled = true;
};
You don't need Task.Run if the only async work you have is to await a Task.Delay. But if you do have more async work to do, then it's better to use Task.Run for this work only:
sendShortDataButton.Click += async (sender, e) =>
{
var button = (Button)sender;
button.Enabled = false;
await Task.Run(async () =>
{
await Task.Delay(1000); // Simulate async work
});
button.Enabled = true;
};

How to use async task as a method with parameters

I get confused, when tried to use async task. Everything is fine if I use this method without parameters, but when I add parameters to it, it says that cannot convert System.Threading.Tasks.Task to System.Func. So how to use it properly and fix this error?
Main:
Timers t = new Timers();
public Form1()
{
InitializeComponent();
t.StartTimerTemplate(TEMPLATEupdateSong("test", "test", "test"));//error occurs in this line
}
async Task TEMPLATEupdateSong(string url, string sender, string labelName)
{
string nowPlaying = await getter.getString(url);
nowPlaying = XDocument.Parse(nowPlaying).ToString();
var outputLabel = this.Controls.OfType<Label>()
.FirstOrDefault(control => control.Name == labelName);
outputLabel.Invoke(new Action(() =>
outputLabel.Text = sender + "\n" + nowPlaying
));
}
Timers.cs:
public void StartTimerTemplate(Func<Task> updateTemplate)
{
System.Timers.Timer timer = new System.Timers.Timer(50000);
timer.AutoReset = true;
timer.Elapsed += (sender, e) => timer_Elapsed(sender, e, updateTemplate());
timer.Start();
}
async void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e, Task task)
{
await task;
}
Your method expects a Func<Task>, not a Task.
t.StartTimerTemplate(() => TEMPLATEupdateSong("test", "test", "test"));
Or
t.StartTimerTemplate(async () => await TEMPLATEupdateSong("test", "test", "test"));

Trying to start a dialog after bool task, application stucks

When i'm using async task result inside bool button application is stuck
async Task<bool> task1()
{
await Task.Run(() =>
{
for (int a = 0; a <= 1000000000; a++)
{
}
});
return true;
}
private void Start_Click(object sender, EventArgs e)
{
setDialog(true);
if (task1().Result==true)
setDialog(false);
}
private void setDialog(bool show)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetView(Resource.Layout.layout1);
Dialog dialog = builder.Create();
dialog.SetCancelable(false);
if (show) dialog.Show();
else dialog.Dismiss();
}
When i'm pressing start button click my application is stuck and doesnt let me do anything.
If i will use task inside button event then everything is going fine
You deadlocked your application. This: task1().Result waits synchronously and defeats the purpose of tasks. Use async/await like this instead:
private async void Start_Click(object sender, EventArgs e)
{
setDialog(true);
var result = await task1();
if (result)
setDialog(false);
}

NFC-reader on Win IOT: Pin ' is currently opened in an incompatible sharing mode

I am working on a NFC reader project based on Windows 10 IoT running on a Rasperry PI 3.
I use the library Mfrc522lib.cs found here: RFID RC522 Raspberry PI 2 Windows IOT.
I use an async task to wait for the card. It scans perfect the first time, but when I start the task again (for test puprose with button).
I get this:
Pin ' is currently opened in an incompatible sharing mode. Make sure this pin is not already in use by this application or another Application
Any idea?
public MainPage()
{
this.InitializeComponent();
startNFC();
}
public void startNFC()
{
var read = ReadNFCAsync();
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Your UI update code goes here!
this.serial.Text = "Klar for å lese kortet ditt";
this.statusline.Fill = new SolidColorBrush(Colors.Green);
});
read.ContinueWith(prev => {
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Your UI update code goes here!
this.serial.Text = prev.Result.ToString();
this.statusline.Fill = new SolidColorBrush(Colors.Orange);
});
});
}
public static async Task<String> ReadNFCAsync()
{
await Task.Delay(1000);
var mfrc = new Mfrc522();
await mfrc.InitIO();
while (true)
{
if (mfrc.IsTagPresent())
{
var uid = mfrc.ReadUid();
var serial= uid.ToString();
mfrc.HaltTag();
return serial;
}
}
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
startNFC();
}
This issue due to initializing GPIO pin is in use. Because every time you click the button the following line will be executed:
await mfrc.InitIO();
To solve this problem you can edit your code like this:
private Mfrc522 mfrc = new Mfrc522();
public static bool IsGpioInitialized = false;
public async Task ReadNFCAsync()
{
if (!IsGpioInitialized)
{
await mfrc.InitIO();
IsGpioInitialized = true;
}
}

Categories

Resources