【发布时间】:2018-11-15 20:05:36
【问题描述】:
我是C#的新手,我主要用VB开发.net应用程序。
我开发了 .net WPF 应用程序来连接微软认知服务来获取图像描述并保存到 sql server。
因为我会将它作为计划任务运行,因此我希望它在完成该过程后自动关闭。
应用程序可以正常工作以获取图像描述和更新表。
但如果我添加关闭应用程序功能,它将立即关闭而不启动进程。
我可以知道应用程序如何在关闭应用程序之前等待进程完成吗?
提前致谢。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using Microsoft.ProjectOxford.Vision;
using Microsoft.ProjectOxford.Vision.Contract;
using System.Diagnostics;
namespace TagPhotoScheduler
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Boolean Finished = false;
public MainWindow()
{
InitializeComponent();
ReadFile();
CloseApp();
}
public void CloseApp()
{
//close application after run
if (Finished == true)
{
Application.Current.Shutdown();
//this.Close();
}
}
public void ReadFile()
{
DataClassesTagPhotoDataContext dc = new DataClassesTagPhotoDataContext();
var query = from qPhoto in dc.db_PhotoLibrary_Photos
where qPhoto.ML_Processed == false
select qPhoto;
foreach (var q in query)
{
string pFileName = string.Empty;
string photoURL = string.Empty;
pFileName = q.PhotoID + "." + q.FileType;
_status.Text += pFileName + " | ";
photoURL = "https://example.com/storage/";
if (q.ProjectID == null || q.ProjectID == 0)
{
GetTag(q.PhotoID, photoURL + pFileName);
_status.Text += photoURL + pFileName + " \n";
}
else //had projectid
{
photoURL += q.ProjectID + "/";
if (q.AlbumID == null || q.AlbumID == 0)
{
//photoURL += "/" + q.AlbumID + "/";
GetTag(q.PhotoID, photoURL + pFileName);
_status.Text += photoURL + pFileName + " \n";
}
else //albumid
{
photoURL += q.AlbumID + "/";
GetTag(q.PhotoID, photoURL + pFileName);
_status.Text += photoURL + pFileName + " \n";
}
}
}
//Finished = true;
_status.Text += "\n\nFinished";
}
public async void GetTag(int PhotoID, string URL)
{
VisionServiceClient VisionServiceClient = new VisionServiceClient("xxxxxxxxxxxxxxxxxxxx", "https://eastasia.api.cognitive.microsoft.com/vision/v1.0");
DataClassesTagPhotoDataContext dc = new DataClassesTagPhotoDataContext();
try
{
AnalysisResult analysisResult = await VisionServiceClient.DescribeAsync(URL, 3);
if (analysisResult.Description != null)
{
foreach (var tag in analysisResult.Description.Tags)
{
tags += tag + ", ";
string QueryAnalysis = string.Empty;
db_PhotoLibrary_Photo_Tag newQ = new db_PhotoLibrary_Photo_Tag();
newQ.TagOn = DateTime.Now;
newQ.TagBy = 0;
newQ.PhotoID = PhotoID;
newQ.ML_Tag = true;
newQ.TagType = 0;
newQ.TagName = tag;
dc.db_PhotoLibrary_Photo_Tags.InsertOnSubmit(newQ);
dc.SubmitChanges();
db_PhotoLibrary_Photo result = (from p in dc.db_PhotoLibrary_Photos
where p.PhotoID == PhotoID
select p).SingleOrDefault();
result.ML_Processed = true;
dc.SubmitChanges();
}
_status.Text = tags;
}
}
catch { }
}
}
}
最后,我将其更改为控制台应用程序,它可以完成我的工作。
【问题讨论】:
-
看来您正在以一种即发即弃的方式使用
async void GetTag,这看起来像是这里的核心问题。您可能应该将其设为async Task,然后在退出应用程序之前跟踪所有待处理的任务以完成。滥用async void是一个常见的陷阱,在 SO 上已广泛介绍。 -
ReadFile和GetTag需要为async Task。然后将ReadFile和CloseApp从构造函数中取出。然后您的MainWindow可以将初始化任务公开为seen here。该任务将代表文件访问,并将在您的组合根中等待,对于 WPF,它通常是App.xaml.cs。最后,当初始化任务完成后,应用就可以退出了。 -
另一个考虑因素是为什么你在 WPF 看起来并不需要 UI 时使用它。使用控制台应用程序,您没有任何异步构造函数的复杂性,并且可以轻松地
await ReadFile然后退出。 -
感谢 JSteward。我将其更改为控制台应用程序,它可以完成这项工作。
标签: c# wpf async-await