I have an application which performs the following:
Initialises a connected Webcam
private async Task<MediaCapture> InitialiseWebCam() { MediaCapture webCam = null; webCam = new MediaCapture(); try { await webCam.InitializeAsync(); } catch (Exception ex) { //Log error } return webCam; }
Takes an image
private async Task<StorageFile> TakePicture(MediaCapture webCam) { try { var image = await KnownFolders.PicturesLibrary.CreateFileAsync("TestImage.jpg", CreationCollisionOption.GenerateUniqueName); var imageEncodingProperties = ImageEncodingProperties.CreatePng(); await webCam.CapturePhotoToStorageFileAsync(imageEncodingProperties, image); return image; } catch (Exception ex) { //Log error } return null; }
Uploads image to Azure Blob Storage
private async Task<StorageFile> UploadPictureToAzure(StorageFile image) { string Azure_StorageAccountName = "MYACCOUNTNAME"; string Azure_ContainerName = "MYCONTAINERNAME"; string Azure_AccessKey = "MYACCESSKEY"; try { StorageCredentials creds = new StorageCredentials(Azure_StorageAccountName, Azure_AccessKey); CloudStorageAccount account = new CloudStorageAccount(creds, useHttps: true); CloudBlobClient client = account.CreateCloudBlobClient(); CloudBlobContainer sampleContainer = client.GetContainerReference(Azure_ContainerName); CloudBlockBlob blob = sampleContainer.GetBlockBlobReference(image.Name); await blob.UploadFromFileAsync(image); return image; } catch (Exception ex) { //Log } return image; }
The three methods are invoked as below:
public void Run(IBackgroundTaskInstance taskInstance)
{
Monitor();
}
private void Monitor()
{
var webCam = InitialiseWebCam().Result;
var image = TakePicture(webCam).Result;
var output = UploadPictureToAzure(image).Result;
}
At this point all is well and the image appears in my blob storage. I wanted this behaviour to run as a headless background application on Windows IoT, so I made the following adjustment:
public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.GetDeferral();
timer = ThreadPoolTimer.CreatePeriodicTimer(Timer_Tick, TimeSpan.FromSeconds(60));
}
private void Timer_Tick(ThreadPoolTimer threadPoolTimer)
{
Monitor();
}
With those changes in place the Monitor function is triggered as expected, however the output of UploadPictureToAzure(image).Result
is null even though webCam and image are working as intended, and the application exits abruptly.
What is the reason for the behaviour above? I was expecting the image to be uploaded and the overall process continue to occur within the timer loop created.
EDIT:
I attempted to force synchronous behavior by adjusting my UploadPictureToAzure like so:
private void UploadPictureToAzure(StorageFile image)
{
string Azure_StorageAccountName = "ACCOUNTNAME";
string Azure_ContainerName = "CONTAINERNAME";
string Azure_AccessKey = "ACCESSKEY";
try
{
StorageCredentials creds = new StorageCredentials(Azure_StorageAccountName, Azure_AccessKey);
CloudStorageAccount account = new CloudStorageAccount(creds, useHttps: true);
CloudBlobClient client = account.CreateCloudBlobClient();
CloudBlobContainer sampleContainer = client.GetContainerReference(Azure_ContainerName);
CloudBlockBlob blob = sampleContainer.GetBlockBlobReference(image.Name);
var response = blob.UploadFromFileAsync(image);
response.AsTask().Wait();
}
catch (Exception ex)
{
//Log
}
}
Now even with the call to .Wait(), execution returns immediately and the application exits.
If I remove usage of the ThreadPoolTimer.CreatePeriodicTimer, and replace it with a while loop then images upload without issue.