DispatcherHelper 到线程

发布于 2024-12-06 18:04:20 字数 1134 浏览 0 评论 0原文

我有一个使用 1 个主窗口的应用程序,而该窗口又具有 5 个使用功能区控件创建的用户控件。

在其中一个用户控件上,我启动一个线程:

if (AmtMembersWithEmail > 0)
{
    DispatcherHelper.UIDispatcher.Invoke(new Action(() =>
    {
        max = 100;
        Messenger.Default.Send<ShowProgressWindowMessage>(
                              new ShowProgressWindowMessage(this));
        Progress = 0;
        Thread.Sleep(1000);                               
    }));

因此该线程启动并将进度报告回主窗口,在此期间,当线程执行时,用户无法访问控件或在应用程序中执行任何其他操作,从读取在调度程序上,这是正常的,因为它必须使用单个 UIThread,允许用户与 UI 上的控件进行交互。 (顺便使用 Galasoft MVVM light!)

显示报告进度的窗口有一个命令,该命令绑定到我的视图模型中的中继命令: XAML 进度窗口的摘录如下:

<tk:LoadingAnimation Grid.Row="0" DataContext="{Binding}"/>        
<ContentControl Visibility="{Binding CanBeAborted, 
                Converter={StaticResource VisibilityConverter}}" >
    <Hyperlink Command="{Binding AbortCommand}">cancel</Hyperlink>
</ContentControl>

有没有办法使用调度程序来允许线程在后台运行?或者用户只需等待操作完成?

要补充的是,线程实际上所做的工作是循环客户数据、创建附件(发票)并为每个客户创建电子邮件对象,然后最终循环新电子邮件集合并将每封电子邮件单独发送给客户...

任何帮助都是非常感谢....

I have an application which uses 1 Main Window and in turn this window has 5 UserControls which are created using a Ribbon Control.

On one of the user controls I kick off a thread :

if (AmtMembersWithEmail > 0)
{
    DispatcherHelper.UIDispatcher.Invoke(new Action(() =>
    {
        max = 100;
        Messenger.Default.Send<ShowProgressWindowMessage>(
                              new ShowProgressWindowMessage(this));
        Progress = 0;
        Thread.Sleep(1000);                               
    }));

So this thread kicks off and reports progress back to the main window, during this time, as the thread executes the user cannot access the controls or do anything else within the application, from reading up on the dispatcher this is normal as it must use the single UIThread which allows the user to interact with controls on the UI. ( Using Galasoft MVVM light by the way! )

The window that displays reporting the progress has a command which binds to a relay command in my viewmodel: Extract from XAML progress window is below:

<tk:LoadingAnimation Grid.Row="0" DataContext="{Binding}"/>        
<ContentControl Visibility="{Binding CanBeAborted, 
                Converter={StaticResource VisibilityConverter}}" >
    <Hyperlink Command="{Binding AbortCommand}">cancel</Hyperlink>
</ContentControl>

Is there any way to use the dispatcher to allow the thread to run in the background? or will the user just have to wait until the operation completes?

To add, the work the thread is actually doing is looping customer data, creating attachments ( invoices ) and creating an email object for each customer before finally looping that new email collection and sending each email individually to the customer...

Any help would be greatly appreciated....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

各自安好 2024-12-13 18:04:20

我不完全清楚你的处理逻辑是否在用户控件(即代码隐藏)中,或者在你的视图模型中。如果它在您的 ViewModel 中,那么我认为您走在正确的轨道上。

我建议不要使用调度程序,而是旋转一个BackgroundWorker:

    public void DoWork()
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += (sender, e) =>
        {
            //Processing Logic here
        };
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Work_Completed);
        worker.RunWorkerAsync();
    }

    void Work_Completed(object sender, RunWorkerCompletedEventArgs e)
    {

    }

这不会在UI线程上运行,因此您的用户控件应该具有响应能力。另外,正如威尔所建议的,不要终止线程。您的中止逻辑应该优雅地退出处理逻辑内部的循环,清理它使用的资源并执行您需要完成的任何撤消工作。

I am not completely clear whether you have your processing logic in the User Control (i.e. Code Behind), or in your ViewModel. If it's in your ViewModel, then I think you're on the right track.

Instead of using the dispatcher, I suggest spinning a BackgroundWorker:

    public void DoWork()
    {
        BackgroundWorker worker = new BackgroundWorker();
        worker.DoWork += (sender, e) =>
        {
            //Processing Logic here
        };
        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Work_Completed);
        worker.RunWorkerAsync();
    }

    void Work_Completed(object sender, RunWorkerCompletedEventArgs e)
    {

    }

This will not run on the UI thread, therefore your User Control should be responsive. Also, as Will as suggested, DO NOT TERMINATE THREADS. Your Abort logic should gracefully exit the loop inside of your processing logic, cleaning up the resources it used and performing any undo work you need done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文