我有一个每15秒调用一次方法的计时器,该方法需要一些时间才能完成。
我已经尽可能地将它转换为async
,但是当它运行时它仍然会冻结UI几乎1秒,并且因为它每15秒运行一次,它就变得烦人了。
知道如何让这个async
方法完全脱离网格吗?
这是计时器方法:
public static DispatcherTimer UpdateList = new DispatcherTimer();
//GlobalVars.MainList = new List<string>(); //saved list from previous declaration
public MainFunction()
{
this.InitializeComponent();
UpdateList.Tick += UpdateList_Tick; ;
UpdateList.Interval = new TimeSpan(0, 0, 0, 0, 15000);
UpdateList.Start();
//...
}
private async void UpdateList_Tick(object sender, object e)
{
using (var client = new ImapClient())
{
using (var cancel = new CancellationTokenSource())
{
await client.ConnectAsync("imap.gmail.com", 993, true, cancel.Token);
client.AuthenticationMechanisms.Remove("XOAUTH");
await client.AuthenticateAsync("email.com", "mail12345", cancel.Token);
var inbox = client.Inbox;
await inbox.OpenAsync(FolderAccess.ReadOnly, cancel.Token);
// let's try searching for some messages...
DateTime date = DateTime.Now;
DateTime mondayOfLastWeek = date.AddDays(-(int)date.DayOfWeek - 6);
var query = SearchQuery.DeliveredAfter(mondayOfLastWeek)
.And(SearchQuery.SubjectContains("search"))
.And(SearchQuery.All);
List<string> newList = new List<string>();
foreach (var uid in inbox.Search(query, cancel.Token))
{
var message = inbox.GetMessage(uid, cancel.Token);
string trimmedMSGEmtyLines = Regex.Replace(message.TextBody, @"^\s+$[\r\n]*", "", RegexOptions.Multiline);
newList.Add(message.Date.LocalDateTime + Environment.NewLine + trimmedMSGEmtyLines);
}
await client.DisconnectAsync(true, cancel.Token);
if (!GlobalVars.MainList.SequenceEqual(newList))
{
GlobalVars.MainList = newList;
}
}
}
}
答案 0 :(得分:1)
async / await
在执行长时间运行的操作时非常有用,这些操作在UI线程上运行时与UI分离。这正是你正在做的事情 - 但是你似乎首先没有在UI线程上做生意。实际上,您可以 await
事件处理程序的整个内容,因为它完全与UI分离。因此,这不适合这项工作。
BackgroundWorker
,这将是一个很好的选择。我选择使用System.Threading.Timer
提供解决方案,因为与现有代码相比,没有太多代码需要更改。如果添加任何更新UI的代码,则需要将其调用回调度程序线程。
所有这些异步方法都可能同步运行。我会删除async / await
,然后选择同步方法,例如client.ConnectAsync()
&gt;&gt; client.Connect()
public System.Threading.Timer UpdateTimer;
public MainFunction()
{
this.InitializeComponent();
UpdateTimer = new System.Threading.Timer(UpdateList_Tick);
UpdateTimer.Change(0, 15000);
//...
}
private async void UpdateList_Tick(object state)
{
using (var client = new ImapClient())
{
using (var cancel = new CancellationTokenSource())
{
await client.ConnectAsync("imap.gmail.com", 993, true, cancel.Token);
client.AuthenticationMechanisms.Remove("XOAUTH");
await client.AuthenticateAsync("email.com", "mail12345", cancel.Token);
var inbox = client.Inbox;
await inbox.OpenAsync(FolderAccess.ReadOnly, cancel.Token);
// let's try searching for some messages...
DateTime date = DateTime.Now;
DateTime mondayOfLastWeek = date.AddDays(-(int)date.DayOfWeek - 6);
var query = SearchQuery.DeliveredAfter(mondayOfLastWeek)
.And(SearchQuery.SubjectContains("search"))
.And(SearchQuery.All);
List<string> newList = new List<string>();
foreach (var uid in inbox.Search(query, cancel.Token))
{
var message = inbox.GetMessage(uid, cancel.Token);
string trimmedMSGEmtyLines = Regex.Replace(message.TextBody, @"^\s+$[\r\n]*", "", RegexOptions.Multiline);
newList.Add(message.Date.LocalDateTime + Environment.NewLine + trimmedMSGEmtyLines);
}
await client.DisconnectAsync(true, cancel.Token);
if (!GlobalVars.MainList.SequenceEqual(newList))
{
GlobalVars.MainList = newList;
}
}
}
}