我有一个执行以下操作的应用程序:
初始化连接的网络摄像头
private async Task<MediaCapture> InitialiseWebCam()
{
MediaCapture webCam = null;
webCam = new MediaCapture();
try
{
await webCam.InitializeAsync();
}
catch (Exception ex)
{
//Log error
}
return webCam;
}
拍摄图像
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;
}
将图像上传到Azure Blob存储
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;
}
调用这三种方法如下:
public void Run(IBackgroundTaskInstance taskInstance)
{
Monitor();
}
private void Monitor()
{
var webCam = InitialiseWebCam().Result;
var image = TakePicture(webCam).Result;
var output = UploadPictureToAzure(image).Result;
}
此时一切正常,图像出现在我的blob存储中。我希望此行为作为Windows IoT上的无头后台应用程序运行,因此我进行了以下调整:
public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.GetDeferral();
timer = ThreadPoolTimer.CreatePeriodicTimer(Timer_Tick, TimeSpan.FromSeconds(60));
}
private void Timer_Tick(ThreadPoolTimer threadPoolTimer)
{
Monitor();
}
根据这些更改,Monitor功能会按预期触发,但UploadPictureToAzure(image).Result
的输出为空,即使 webCam 和图像按预期工作,应用程序突然退出。
上述行为的原因是什么?我期待上传图像,整个过程继续在创建的定时器循环中发生。
修改
我试图通过调整我的UploadPictureToAzure来强制同步行为:
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
}
}
现在即使调用 .Wait(),执行也会立即返回并退出应用程序。
如果我删除 ThreadPoolTimer.CreatePeriodicTimer 的使用情况,并将其替换为while循环,则图片上传时不会出现问题。
答案 0 :(得分:0)
使用异步方法的方法是,他们倾向于抓取您的代码并将其全部入侵:)...您必须使用await
关键字而不是调用Result
属性,否则在尝试获取结果之前,您无法确定该函数是否已完成执行。这适用于代码中的所有异步方法。
将您的Monitor方法更改为异步并返回Task
,如下所示:
private async Task Monitor()
{
var webCam = await InitialiseWebCam();
var image = await TakePicture(webCam);
var output = await UploadPictureToAzure(image);
}
我猜测Windows手机在顶层有一个异步API,所以你可以等到主线程,但如果没有,here are a couple of workarounds to call async methods synchronously
编辑:
每Quickstart: Create and register a background task (XAML)您可以在Run方法上执行以下操作:
public async void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral _deferral = taskInstance.GetDeferral();
ThreadPoolTimer.CreatePeriodicTimer(async(timer) => {
await Monitor();
_deferral.Complete();
}, TimeSpan.FromSeconds(60));
}
答案 1 :(得分:-1)
最后,我能够使用以下代码实现我的需求:
private readonly TimeSpan _delayDuration = TimeSpan.FromMinutes(20);
public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.GetDeferral();
do
{
try
{
Monitor().Wait();
}
/* SNIP */
}
while (true);
private async Task Monitor()
{
var webCam = await InitialiseWebCam();
var image = await TakePicture(webCam);
await UploadPictureToAzure(image);
await Task.Delay(_delayDuration);
}
private async Task UploadPictureToAzure(StorageFile image)
{
var Azure_StorageAccountName = "accountname";
var Azure_ContainerName = "container";
var Azure_AccessKey = "key";
try
{
StorageCredentials creds = new StorageCredentials(Azure_StorageAccountName, Azure_AccessKey);
CloudStorageAccount account = new CloudStorageAccount(creds, true);
CloudBlobClient client = account.CreateCloudBlobClient();
CloudBlobContainer sampleContainer = client.GetContainerReference(Azure_ContainerName);
CloudBlockBlob blob = sampleContainer.GetBlockBlobReference(image.Name);
await blob.UploadFromFileAsync(image);
}
catch (Exception ex)
{
/* Logging */
throw ex;
}
}
private async Task<MediaCapture> InitialiseWebCam()
{
var webCam = new MediaCapture();
try
{
await webCam.InitializeAsync();
}
catch (Exception ex)
{
/* Logging */
throw ex;
}
return webCam;
}
private async Task<StorageFile> TakePicture(MediaCapture webCam)
{
try
{
var image = await KnownFolders.PicturesLibrary.CreateFileAsync("Image.png", CreationCollisionOption.ReplaceExisting);
var imageEncodingProperties = ImageEncodingProperties.CreatePng();
await webCam.CapturePhotoToStorageFileAsync(imageEncodingProperties, image);
return image;
}
catch (Exception ex)
{
/* Logging */
throw ex;
}
}