2016-08-30 90 views
-2

下面的情況C#WPF - 顯示文本使用延遲

按鈕按下

顯示文本框 「成功訂購」

延遲2秒仍呈現文本

延時結束和文字進行修改/消失到「放置您的芯片」

問題:

使用線程休眠它顯示文本之前凍結整個用戶界面,延遲後出現第二個文本。有趣的是,我改變文字後播放的聲音播放,但文字沒有顯示。

使用任務(異步/延遲/等待)它不會等待延遲,只是在一行中顯示,所以首先文本很短的時間,然後立即改變爲第二文本。

使用任務(等待)程序崩潰。

使用計時器它與使用任務(異步或/和延遲)具有相同的效果。

使用while(時間,第二次+2秒)現在只是將新時間推到時間上,如果時間結束,它就完成了,但與Thread Sleep有相同的效果 - 整個UI凍結。


也許有趣的是,有一些計時器在後臺運行。

我嘗試了很多我在這裏找到的版本,但都沒有工作 - 也許是關於WPF,所以我現在問如果有人有WPF延遲的解決方案。

代碼

 private void SendWithDelay() 
     { 
      // close(); // Sets text back to "place your chip" but for here: 
      tbPlace.Text = "Place your chip"; 
     } 

     private void changeVisibilityForDelay() 
     { 
       // called by pressed button 
       tbPlace.Text = "Successfully ordered"; 
       tbPlace.Visibility = Visibility.Visible; 
       Task.Delay(2000).ContinueWith(t => SendWithDelay(), TaskScheduler.FromCurrentSynchronizationContext()); 
     } 
+0

通過MCVE @ASh表示*最小,完整和可驗證示例*:http:// stackoverflow。com/help/mcve – user3185569

+0

對不起,添加了一個我試過的例子 – iDraGoN

回答

1

(使用System.Windows.Threading程序;)
是這樣的:

private void startTimer(){ 
    Thread timerThread = new Thread(runTimer); 
    timerThread.Start(); 
} 

private async void runTimer(){ 
    await Task.Delay(2000); 
    Dispatcher.BeginInvoke(new Action(() => updateScreen())); 
} 

private void updateScreen(){ 
    TextBox1.Text = "This is delayed"; 
} 
+0

WPF似乎沒有調用/ MethodInvoker,因爲它不顯示任何使用的解決方案? – iDraGoN

+0

對不起 - 我錯過了WPF的一部分。嘗試使用System.Windows.Threading.Dispatcher.Invoke代替Invoke(new MethodInvoker()) –

+0

是的,發現了Dispatcher.Invoke,但現在想要替換MethodInvoker,好像我需要使用Action委託。 – iDraGoN

1

最小例如用System.Threading.Timer。還使用INotifyPropertyChanged Interface通過WPF Data Bindings更新UI中的更改。 XAML代碼:

<Window x:Class="WpfTimerExample.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" 
     mc:Ignorable="d" 
     SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen" Title="WPF and System.Threading.Timer"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <StackPanel Grid.Row="0" Orientation="Vertical"> 
      <TextBlock Text="Text is: " /> 
      <TextBlock Text="{Binding Text}" /> 
      <TextBlock Text="TimeDiff: " /> 
      <TextBlock Text="{Binding TimeDiff}" /> 
     </StackPanel> 
     <StackPanel Grid.Row="1"> 
      <Button Name="btnTimerExample" Content="Click to start Timer example" 
        Click="btnTimerExample_Click"/> 
     </StackPanel> 
    </Grid> 
</Window> 

代碼:

using System; 
using System.ComponentModel; 
using System.Threading; 
using System.Windows; 

namespace WpfTimerExample 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     readonly TimeSpan TIMER_DUE_TIME = TimeSpan.FromSeconds(2); 
     readonly TimeSpan TIMER_PERIOD = TimeSpan.FromMilliseconds(-1); 

     DateTimeOffset _timeWhenButtonClicked; 
     DateTimeOffset _timeWhenTimerFired; 
     Timer _timer; 
     string _Text; 
     TimeSpan _TimeDiff; 

     public event PropertyChangedEventHandler PropertyChanged = delegate { }; 

     public string Text 
     { 
      get { return _Text; } 
      set { _Text = value; PropertyChanged(this, new PropertyChangedEventArgs("Text")); } 
     } 
     public TimeSpan TimeDiff 
     { 
      get { return _TimeDiff; } 
      set { _TimeDiff = value; PropertyChanged(this, new PropertyChangedEventArgs("TimeDiff")); } 
     } 

     public MainWindow() 
     { 
      DataContext = this; 
      Text = "Successfully ordered"; 
      InitializeComponent(); 
     } 
     private void btnTimerExample_Click(object sender, RoutedEventArgs e) 
     { 
      Text = "Successfully ordered"; 
      TimeDiff = TimeSpan.Zero; 

      _timeWhenButtonClicked = DateTimeOffset.UtcNow; 
      // If there is no timer 
      if (_timer == null) { 
       // Create and start timer. 
       // Call TimerHandler just one time after 2 seconds 
       _timer = new Timer(TimerHandler, null, TIMER_DUE_TIME, TIMER_PERIOD); 
      } 
      else // if exist, just restart it 
       _timer.Change(TIMER_DUE_TIME, TIMER_PERIOD); 
     } 
     private void TimerHandler(object state) 
     { 
      _timeWhenTimerFired = DateTimeOffset.UtcNow; 
      Text = "Place your chip"; 
      TimeDiff = _timeWhenTimerFired - _timeWhenButtonClicked; 
     } 
     protected override void OnClosed(EventArgs e) 
     { 
      if (_timer != null) 
       _timer.Dispose(); 
     } 
    } 
} 
1

您可以DispatcherTimer嘗試在這種情況下。請嘗試以下示例 添加兩個一個按鈕和一個文本框。 在代碼 後面添加

DispatcherTimer OBJ =新DispatcherTimer();

private void button_Click(object sender, RoutedEventArgs e) 
    { 
     textBox.Text = "Successfully ordered"; 
     obj.Interval = new TimeSpan(0, 0, 2); 
     obj.Start(); 
     obj.Tick += Obj_Tick; 
    } 

    private void Obj_Tick(object sender, EventArgs e) 
    { 
     textBox.Text = "Place your chip"; 
     obj.Stop(); 
    } 
+0

它使用您的代碼立即將文本更改爲「放置您的芯片」 – iDraGoN

+0

好吧,對不起,它可以工作 - 另一位程序員有另一個地方使用「放置您的芯片」文本並覆蓋我/您的代碼。 – iDraGoN