C# 打开窗口的WPF背景方法
我目前正在开发一个应用程序,通过IMAP检查来自电子邮件帐户的电子邮件。此函数每5秒调用一次,需要一些时间才能完成C# 打开窗口的WPF背景方法,c#,wpf,C#,Wpf,我目前正在开发一个应用程序,通过IMAP检查来自电子邮件帐户的电子邮件。此函数每5秒调用一次,需要一些时间才能完成 private void CheckForRequests() { List<string[]> mails = CollectAllMails(); for (int i = 0; i < mails.Count; i++) { if (mails[i][0].Split(
private void CheckForRequests()
{
List<string[]> mails = CollectAllMails();
for (int i = 0; i < mails.Count; i++)
{
if (mails[i][0].Split('_')[0] == "request")
{
//INVITATION TO ME
if (mails[i][0].Split('_')[2] == username && mails[i][0].Split('_')[3] == "request")
{
DeleteMail(mails[i][0]);
MessageBoxResult result = MessageBox.Show("Do you accept the request from " + mails[i][0].Split('_')[1], "Invitation", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes);
if (result == MessageBoxResult.Yes)
{
DeleteMail("request_" + mails[i][0].Split('_')[1] + "_" + mails[i][0].Split('_')[2] + "_" + mails[i][0].Split('_')[3]);
SendMail("request_" + mails[i][0].Split('_')[1] + "_" + mails[i][0].Split('_')[2] + "_accept", "");
ChatWindow chat = new ChatWindow();
chat.ShowDialog();
//do open chat window
}
else if (result == MessageBoxResult.No)
{
DeleteMail("request_" + mails[i][0].Split('_')[1] + mails[i][0].Split('_')[2]);
SendMail("request_" + mails[i][0].Split('_')[1] + "_" + mails[i][0].Split('_')[2] + "_decline", "");
}
}
//ACCEPTION FROM ANOTHER DUDE
else if (mails[i][0].Split('_')[2] != username && mails[i][0].Split('_')[3] == "accept")
{
ChatWindow chat = new ChatWindow();
chat.ShowDialog();
}
//REJECTION FROM ANOTHER DUDE
else if (mails[i][0].Split('_')[2] != username && mails[i][0].Split('_')[3] == "decline")
{
MessageBox.Show("Your invitation was declined.", "Sorry", MessageBoxButton.OK, MessageBoxImage.Exclamation);
}
}
else if (mails[i][0].Split('_')[0] == "somethingelse")
{
}
}
}
private void CheckForRequests()
{
列表邮件=CollectAllMail();
for(int i=0;i
我的循环每5秒调用一次这个方法,在这段时间里,我无法在我的应用程序中编写或执行任何操作。我很确定我必须使用线程
或任务
来解决这个问题,但我没有找到与我的案例相关的方法。当我在任务
中调用该方法时,我单击Yes,它崩溃并说它必须是STA线程
。。。在这种情况下,我甚至不想用线程访问GUI,我只想检查邮件,如果方法发现了什么,它应该做一些事情,比如从任务中断并调用一个方法(而不是从任务)
对于这个问题,最干净的解决方案是什么?线程问题是由于您试图在非UI线程上执行UI操作造成的。您可以通过在任何时候调用这样的UI内容来解决这个问题
Application.Current.Dispatcher.Invoke(() =>
{
// Your stuff here
});
void CheckForRequests()
{
// Do stuff
Application.Current.Dispatcher.Invoke(() =>
{
// Open your message box
});
// Do more stuff
Application.Current.Dispatcher.Invoke(() =>
{
// Open another message box
});
}
所以在你的情况下,你会有这样的东西
Application.Current.Dispatcher.Invoke(() =>
{
// Your stuff here
});
void CheckForRequests()
{
// Do stuff
Application.Current.Dispatcher.Invoke(() =>
{
// Open your message box
});
// Do more stuff
Application.Current.Dispatcher.Invoke(() =>
{
// Open another message box
});
}
您关于需要使用线程的看法是正确的 虽然@Gareth关于需要使用调度器正确地跨硬盘访问元素的观点是正确的,但我实际上没有看到代码中有任何线程,尽管错误消息清楚地证明您尝试了一些 要实现线程化,您有多种选择 首先,您可以通过任务或旧的线程类直接执行此操作 这样做很简单
private void CheckForRequestsAsync()=>Task.Run(()=>CheckForRequests())代码>
这将立即创建并启动一个任务,该任务将在一个单独的线程中执行CheckForRequests,从而使GUI能够继续在GUI上工作,然而,这是一个非常基本的实现,在可靠地满足您的需求之前,可能需要进一步的增强
另一个选择是利用.Net中的一些较新功能并使用async关键字
如果将CheckForRequests声明为私有异步void CheckForRequests(objectsender,EventArgs e)
,则void将自动转换为一个任务,该任务可由事件处理程序作为异步任务(例如
乙二醇
结合@Gareth建议的任何抛出跨线程访问异常的调度程序信息,您应该准备好了
这看起来像这样:
MessageBoxResult result = Dispatcher.Invoke(() =>
MessageBox.Show("Do you accept the request from " + mails[i][0].Split('_')[1], "Invitation", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes);
);
注意:如果使用async
而不使用wait
关键字,则会收到警告,提示您的线程可能在任何工作线程完成之前退出,然而,这只是一个警告,如果您没有在方法中调用任何工作线程,或者您不需要在退出之前完成它们,那么不会造成任何伤害
最后
其中一条评论建议使用Dispatcher而不是计时器,我不建议这样做,因为每次计时器滴答作响时,它都会在GUI线程中运行您的代码,正如您已经看到的那样,锁定它。当计时器大量更改GUI并快速运行时,最好使用Dispatcher
虽然如果您重新定义了代码,那么您可以通过将gui元素从缓慢运行的进程中分离出来来使用Dispatcher
dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += (s,e)=>{
if( MessageBox.Show("Do you accept the request", "Invitation", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes) == MessageBoxResult.Yes)
{
Task.Run(()=>CheckForRequests());
}
}
dispatcherTimer.Interval = new TimeSpan(0,0,1);
dispatcherTimer.Start();
你是在计时器中创建线程吗?你说你“甚至不想用线程访问GUI”,这让我很困惑,但在你“单击是”后,它崩溃了。MessageBox是GUI的一部分-那么您是否想要这种交互?@Abhishek Yes在Dispatchermer
@PaulF中我也很困惑。我真的只想在线程中检查邮件,但在线程外执行messagebox和其他操作