0

<Border>このクリックイベント内には<Image>さらに<Textblock>長い操作があるため、この操作が完了するまでテキストブロックのテキストは変更されません。

も試しDispatcher.BeginInvoke()ましたが、成功しませんでした。

これが私のコードです:

<Border x:Name="btnReadMe" Grid.Row="0" Style="{StaticResource BorderStyle1}" MouseLeftButtonDown="btnReadMe_MouseLeftButtonDown" MouseLeftButtonUp="btnReadMe_MouseLeftButtonUp" >
    <Border.Background>
        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
            <GradientStop Color="#46c746" Offset="0"/>
            <GradientStop Color="#129312" Offset="1"/>
        </LinearGradientBrush>
    </Border.Background>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="6*"/>
        </Grid.ColumnDefinitions>
        <Image Grid.Column="0" Source="/CareFamily.AtHome;component/Resources/read_message-read_it.png" Margin="5,15" >
            <Image.RenderTransform>
                <ScaleTransform ScaleX="1" ScaleY="1"/>
            </Image.RenderTransform>
        </Image>
        <StackPanel Grid.Column="1" Margin="0,10,0,10"  VerticalAlignment="Center">
            <TextBlock Name="tbReadToMe" Text="Read to Me" Style="{StaticResource TextBlockStyle1}" Margin="0,0,0,0"  />
        </StackPanel>
    </Grid>
</Border>

SpVoice voice;
private void btnReadMe_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (voice == null)
        voice = new SpVoice();


    string readMessageState = tbReadToMe.Text;
    switch (readMessageState)
    {
        case "Read to Me":
            {
                tbReadToMe.Text = "Pause";
                break;
            }

        case "Pause":
            {
                tbReadToMe.Text = "Resume";
                voice.Pause();
                break;
            }

        case "Resume":
            {
                tbReadToMe.Text = "Pause";
                voice.Resume();
                break;
            }
        default:
            {
                tbReadToMe.Text = "Read to Me";
                break;
            }
    }


    if (!string.IsNullOrEmpty(Msg.Subject))
    {
        voice.Speak(Msg.Subject, SpeechVoiceSpeakFlags.SVSFDefault);
    }
    if (!string.IsNullOrEmpty(Msg.Body))
    {
        voice.Speak(Msg.Body, SpeechVoiceSpeakFlags.SVSFDefault); // Length operation
    }
}
4

3 に答える 3

1

スレッドで長い操作を実行し、

発車係

それに応じてUIを更新します。

コード例:

var opThread = new Thread(delegate()
{
    //your lengthy operation

    tbReadToMe.Dispatcher.Invoke(new Action(delegate
    {
        tbReadToMe.Text = "Pause";
    }));

    //your lengthy operation

    tbReadToMe.Dispatcher.Invoke(new Action(delegate
    {
        tbReadToMe.Text = "etc...";
    }));
});

opThread.Start();
于 2012-05-23T11:50:20.163 に答える
0

Dispatcher.BeginInvoke() が役に立たなかった理由は、非同期で動作していても、メイン/UI スレッドで動作しているためです。BackgroundWorkerThread クラスを使用して、バックグラウンド スレッドで時間のかかる操作を実行します。

実証するために小さなサンプルを作成しました。

Window1.xaml:

<Window x:Class="BackgroundWorkerExample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="663">
<Grid>
    <TextBox PreviewMouseDown="textBox1_PreviewMouseDown" Height="38" Margin="24,34,26,0" Name="textBox1" VerticalAlignment="Top" FontSize="24">
        The quick Velociraptor jumped over the torpid tapir.
    </TextBox>
</Grid>

Window1.xaml.cs:

using System.Windows;
using System.Windows.Input;
using System.ComponentModel;
using System.Threading;
using System.Windows.Media;
using System;

namespace BackgroundWorkerExample
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }


        void _asyncSpeakerThread_DoWork(object sender, DoWorkEventArgs e)
        {
            // Change color of text to Red to indicate Start of operation
            this.Dispatcher.BeginInvoke(new Action(() =>  { textBox1.Foreground = Brushes.Red; }));

            string text = e.Argument as string;
            //voice.Speak(text, SpeechVoiceSpeakFlags.SVSFDefault); // Lengthy operation 
            Thread.Sleep(1000); // Simulate lengthy operation

            // Change color of text to Black to indicate End of operation
            this.Dispatcher.BeginInvoke(new Action(() => { textBox1.Foreground = Brushes.Black; }));
        }

        private void textBox1_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            BackgroundWorker bw = new BackgroundWorker();

            bw.DoWork += new DoWorkEventHandler(_asyncSpeakerThread_DoWork);
            string workerArgument = textBox1.Text;
            bw.RunWorkerAsync(workerArgument);
        }
    }
}
于 2012-05-23T12:29:38.800 に答える
-1

Application.DoEvents()「長い」操作の前に使用してください!

于 2012-05-23T11:52:18.833 に答える