I am successfully able to call the Web Api deployed on below link from mobile app or console app.
https://dposapi.azurewebsites.net/DPosApi/v1/Configurations/GetAll
Problem is that when i put this call in BackgroundTask in a RunTime Component project and triggers the background task from mobile app than execution hangs on the line of code where i am calling the Web Api. Sample is available on below link.
https://github.com/imranshabbir/Sample
What could be the problem?
Your run method should be async, like this: (note the await before FillProducts() )
public async void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral deferal = taskInstance.GetDeferral();
// do your task here
await FillProducts();
deferal.Complete();
}
Btw. are you sure that the
"execution hangs on the line of code where i am calling the Web Api"
?
In your current code the problem is that the background task is finished before you get the results (without the await the execution hits the deferal.Complete(); line earlier). So in that case you just don't see the results, but that should not be a hang.
But anyway... async/await is the answer.
Related
In windows service we are connecting to multiple mailboxes using Microsoft graph, reading mails and downloading attachments.
We are using separate class for each mailbox and calling each class with Parallel.Invoke() method.
Parallel.Invoke(() =>
{
ParallelThreadOne.MainAsync().Wait();
},
() =>
{
ParallelThreadSecond.MainAsync().Wait();
});
In each thread we are calling Microsoft Graph's GraphServiceClient to get a user token to process further.
Problems:
Windows service running fine but after some time service is in running state but not doing anything and logging also stops.
After restarting the service it works normally with logging.
The service should be running 24x7.
How to resolve this issue?
PLEASE use async and await (Task-based Asynchronous Pattern, TAP). Please read about Task.Run() i.e. https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run?view=net-5.0.
Wait for multiple tasks:
var task1 = DoWorkAsync();
var task2 = DoMoreWorkAsync();
await Task.WhenAll(task1, task2);
Generally you need an interactive login with GraphServiceClient in the first place and may cache this (token). Interactive logins are not possible with Windows services, because of the underlying security sandbox (session 0) which prevents showing forms.
Hint: use a normal console application (or windows forms app) for the login task, cache the token (https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=custom) and read it back in your service.
Regards
I have a web api 2 controller, the client requests the controller for some kind of html generations(consists of images, files etc.). As the process needs some time and I don't want the users to wait, I have followed the following approach in the Controller :
...Controller(){
Task.Run(() =>
{
//calling heavy duty method to download files where Task.WaitAll() resides
DownloadAndRename()
});
}
DownloadAndRename(){
//created some child task here and run them in task.waitall()
//Task.WaitAll() here
}
I have created tasks for every file to download, rename and other processes. Then execute them in Task.WaitAll().
When I locally run the application, everything is okay. But when I deploy to my test server, it was throwing following exception:
Message: System.Threading.ThreadAbortException: Thread was being aborted.
P.S. In my pc, I have only one application running in the app pool, whereas in my test server there are 8 in that particular pool.
How can I overcome the exception?
Update 1: I have tried by removing the task.WaitAll and do the implementation without using Task. Still, I get the thread abort error, I think somehow the Task.Run() get timed out.
I think the issue is a simple misunderstanding of task implementation.
If you want the task to run immediately as a background task, you can add async keyword and Task return type to the Controller action and make DownloadAndRename() async and make it return a Task and then await DownloadAndRename() from inside the controller action scope. The calling thread won't be blocked this way and any code after the task will not be executed until the returned task is complete.
async Task Controller()
{
await DownloadAndRename();
}
If that still doesn't work after removing
Task.WaitAll(), I'd have a read of this as it might genuinely be
timing out as you said or could be exceptioning for another reason:
Why am i getting "Thread was being aborted" in asp.net?
I am working on a windows iot core application running on a rasberry pi3
i tried to create/fetch the device key from the azure iot hub using the methods below
public MainPage()
{
systemName = "RaspIot";
this.InitializeComponent();
/* Register for the unloaded event so we can clean up upon exit */
Unloaded += MainPage_Unloaded;
registryManager = RegistryManager.CreateFromConnectionString(connectionString);
AddDeviceAsync().Wait();
}
private static async Task AddDeviceAsync()
{
Device device;
try
{
device = await registryManager.AddDeviceAsync(new Device(systemName));
}
catch (DeviceAlreadyExistsException)
{
device = await registryManager.GetDeviceAsync(systemName);
}
deviceKey = device.Authentication.SymmetricKey.PrimaryKey;
}
If the device with name "RaspIot" is already registered an exception is thrown.
This is working fine in a .net45 console application. but in the UWP application for the PI3 the exception is thrown (pops up in while debugging) but not captured by the catch). what should i do differently?
I can reproduce your issue. And when running the UWP app using your code, the UI hangs and is not responsive. So it is not a best practice in UWP app.
In the UWP app, you can directly use AddDeviceAsync() without Wait(). It will execute normal and can catch the exception.
But in the console app, the app will exit without getting the task completion if you remove Wait() operator. So they are different.
For calling asynchronous APIs in UWP you can reference this document.
Update:
And it is not recommended register a device in the MainPage function since it will always be executed every time the app is started.
I have created a BackgroundTask to run a WebService, however if i run my solution with debugger attached, everything works fine, slowly, but fine. But when i hit start in the appmanager (webinterface) it always says "failed to start package [MYPACKAGEID]". So what am i missing?
Here is the complete project: https://github.com/naice/HomeAutomation.git
public sealed class StartupTask : IBackgroundTask
{
internal static BackgroundTaskDeferral Deferral = null;
public async void Run(IBackgroundTaskInstance taskInstance)
{
//
// TODO: Insert code to perform background work
//
// If you start any asynchronous methods here, prevent the task
// from closing prematurely by using BackgroundTaskDeferral as
// described in http://aka.ms/backgroundtaskdeferral
//
Deferral = taskInstance.GetDeferral();
await ThreadPool.RunAsync(async workItem => {
RestWebServer restWebServer = new RestWebServer(80);
try
{
// initialize webserver
restWebServer.RegisterController<Controller.Home.Home>();
restWebServer.RegisterController<Controller.PhilipsHUE.Main>();
await restWebServer.StartServerAsync();
}
catch (Exception ex)
{
Log.e(ex);
restWebServer.StopServer();
Deferral.Complete();
}
}, WorkItemPriority.High);
}
}
The point is that there is no problem with the code or even the manifest, it seems that it's just not meant to run while the device is in "headed" mode, you need to set it as a satrtup headless app and then restart the device.
Edit: All these problems are gone with the latest version 10.0.14279.1000 and now the GUI finally works as it should.
I have been struggling with this to and have had great success with this method that might help someone. All is done in Power Shell
Put the device into headless mode, in some way I donĀ“t think this is mandatory but I have not succeeded without it.
Edit: This is not the case any more, it works as it should now.
https://ms-iot.github.io/content/en-US/win10/HeadlessMode.htm
Start the app in headless mode and add it to the startup app list
To see what apps are in the startup list type
IotStartup startup
To add a headless app type in command
IotStartup add headless [Task1]
To add a headless app type in command
IotStartup startup headless [Task1]
To find the app name you can use the command
IotStartup list
To see that your app are in startup list type
IotStartup startup
Then reboot your device!
I have also had some problems related to removing apps from startup and then try to debug them via Visual Studio and in some cases the only solution were to flash the SD card with a new image.
For a complete list of available commands
https://ms-iot.github.io/content/en-US/win10/tools/CommandLineUtils.htm
So I made a simple Windows Phone 8 app that uploads a text file to the user's SkyDrive account. My code works fine while my app is running in the foreground, but when I attempt to upload a text file when my app is closing , it doesn't seem to work.
I'm using the Live Connect SDK v5.3 for WP8.
SDK link: http://msdn.microsoft.com/en-us/library/live/hh826550.aspx
I'm using this piece of code to do the background upload when my app closes (when the user hits "back button" on their phone:
protected override void OnBackKeyPress(CancelEventArgs e)
{
SaveSkyDriveData();
base.OnBackKeyPress(e);
}
public async Task SaveSkyDriveData()
{
var res = await client.BackgroundUploadAsync("me/skydrive", new Uri("/shared/transfers/MyData.txt", UriKind.RelativeOrAbsolute), OverwriteOption.Overwrite);
}
Any ideas why this code doesn't work when the app is closing? I've read through the SDK that says this should work even after the app has been dismissed. Here's the SDK link for uploading files in the background: http://msdn.microsoft.com/en-us/library/live/hh826531.aspx#uploading_files
Thanks!
You cannot upload files during the closing of the app in WP as you only have about 10 seconds to save state before it's shutdown
You might be able to do it during de-activation but it would be a push as the timescales are the same.
A better solution would be to have a background task (scheduled task) that runs and checks for files to upload and does so periodically.
Another alternative depending on your use case would be to use the parse SDK rather than upload to SkyDrive unless there is a specific reason the file needs to be hosted on SkyDrive
Hope this helps
To revive an ancient thread, is this because you aren't awaiting your async task?
protected override **async** void OnBackKeyPress(CancelEventArgs e)
{
**await** SaveSkyDriveData();
base.OnBackKeyPress(e);
}
the compiler should be warning you that nothing is awaiting the task...
so nothing downstream knows that there's work in progress? so any async work that started probably doesn't complete before the app closes.
if that's related, there are other answers about waiting synchronously as well, like using Task.Run(() => SaveSkyDriveData()).Wait(); to make the async thing be synchronous,