Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 打开窗口的WPF背景方法_C#_Wpf - Fatal编程技术网

C# 打开窗口的WPF背景方法

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(

我目前正在开发一个应用程序,通过IMAP检查来自电子邮件帐户的电子邮件。此函数每5秒调用一次,需要一些时间才能完成

    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和其他操作