使异步功能在后台完全运行

时间:2017-03-08 23:03:24

标签: c# asynchronous timer background uwp

我有一个每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;
                    }
                }
            }
}

更新: MailKitPortable.Text.EncodingMimeKit

1 个答案:

答案 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;
            }
        }
    }
}