C# 5.0 使用任务调试表TaskScheduler来运行task

本文介绍了一个WPF应用程序如何通过不同的方式执行异步任务,并展示了如何避免子线程访问主线程资源产生的异常。提供了三种按钮点击事件的处理方法及对应的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

示例效果与winform中this.invoke(new delegete{})跨线程操作资源类似

建立WPF项目,使用4.5框架

mainwindow.xml文件如下

<Window x:Class="TaskSchedulerDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TaskSchedulerDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock Name="ContentTextBlock" HorizontalAlignment="Left" Margin="44,134,0,0" VerticalAlignment="Top" Width="425" Height="40" />
        <Button Content="Sync" HorizontalAlignment="Left" Margin="45,190,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click" />
        <Button Content="Async" HorizontalAlignment="Left" Margin="165,190, 0, 0" VerticalAlignment="Top" Width="75" Click="Button_Click_1" />
        <Button Content="Async OK" HorizontalAlignment="Left" Margin="285,190,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_2" />
    </Grid>
</Window>


mainwindow.xml.cs文件如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Threading.Tasks;

namespace TaskSchedulerDemo
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            //同步运行任务,此时窗体将不作任何响应
            ContentTextBlock.Text = string.Empty;
            try
            {
                string result = TaskMethod().Result;
                ContentTextBlock.Text = result;
            }
            catch(Exception ex)
            {
                ContentTextBlock.Text = ex.InnerException.Message;
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            //异步方式运行任务,窗体可被移动,但抛出子线程访问主线程资源异常
            //但此种方式将存在异常的风险
            ContentTextBlock.Text = string.Empty;
            Mouse.OverrideCursor = Cursors.Wait;
            Task<string> task = TaskMethod();
            task.ContinueWith(t =>
            {
                ContentTextBlock.Text = t.Exception.InnerException.Message;
                Mouse.OverrideCursor = null;
            }, 
            CancellationToken.None, 
            TaskContinuationOptions.OnlyOnFaulted,
            TaskScheduler.FromCurrentSynchronizationContext());
           
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            //异步方式运行任务,窗体可被移动,子线程可访问主线程资源
            ContentTextBlock.Text = string.Empty;
            Mouse.OverrideCursor = Cursors.Wait;
            //区别在这
            Task<string> task = TaskMethod(TaskScheduler.FromCurrentSynchronizationContext());
            task.ContinueWith(t =>
            {
                Mouse.OverrideCursor = null;
            },
            CancellationToken.None,
            TaskContinuationOptions.None,
            TaskScheduler.FromCurrentSynchronizationContext());
        }

        Task<string> TaskMethod()
        {
            return TaskMethod(TaskScheduler.Default);
        }

        Task<string> TaskMethod(TaskScheduler scheduler)
        {
            //采用task延迟方式可中断延迟,而thread.sleep()则不能
            //await Task.Delay(TimeSpan.FromSeconds(5), cancellationTokenSource.Token);
            Task delay = Task.Delay(TimeSpan.FromSeconds(5));

            return delay.ContinueWith(t =>
            {
                string str = string.Format("task is running on a thread id {0}. is thread pool thread: {1}",
                Thread.CurrentThread.ManagedThreadId,
                Thread.CurrentThread.IsThreadPoolThread);
                // ContentTextBlock为主线程资源
                ContentTextBlock.Text = str;
                return str;
            }, scheduler);
        }
    }
}


运行如下:

注意异常提示的区别,中文为程序运行产生,英文为计划输出


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值