2016-03-26 8 views
1

私はMediaElementを使用するWPFアプリケーションを持っています。 ビデオの特定の部分をループしたいと思います。私はループの目的のためにStartTimeEndTimeの変数を持っています。私はループの目的のためにDispatcherTimerを試しましたが、1秒以下のループでは遅すぎます。だから私は単純なwhileループを以下のようにしようとしました。上記のコードでwhileループでボタンを押すとキャッチ

while (true) 
{ 
    if(!buttonPressed) 
    { 
      while (mePlayer.Position < loop.EndTime) ; //go till end of loop 
      mePlayer.Position = loop.StartTime; //after reaching end of loop start again 
    } 
} 

も0.5秒の映像が正しくループが、 上記のアプローチの問題点は、ループは、それが故にボタンの押下を検出することができないしながら、無限の入力後、私はループを停止することができませんということです。だから私の質問は、私はビデオをループを停止し、他のタスクを続け続けることができるように、whileループのボタンプレスを検出する方法です?

+0

理由だけではなく、バウンドの変化を検出/イベントをキャッチしていませんプロパティの代わりにループ?チェックしていないが、確かにプレイヤーはPositionChangedイベントなどを持っている。 –

+0

私はちょうどチェックし、私は何もPositionChangedイベントを見つけませんでした –

+0

そうです... –

答えて

1

ビデオ再生の進行状況に関する情報を得ることができないのに驚いています。しかし、UIをブロックせずにTaskDispatcher(クロススレッドのため)を組み合わせることで、以下のようにすることができます。

MainWindow.xaml.cs

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private CancellationTokenSource _tokenSource; 
    private double _start; 
    private double _stop; 

    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this; 

     media.LoadedBehavior = MediaState.Manual; 
     Start = 0; 

     media.MediaOpened += (sender, args) => 
     { 
      Stop = (int)media.NaturalDuration.TimeSpan.TotalSeconds; 
      SetEndPosition(); 
     }; 
     media.Source = new Uri("video.wmv", UriKind.Relative); 
     media.Play(); 
    } 

    private async void SetEndPosition() 
    { 
     _tokenSource?.Cancel(); 
     _tokenSource = new CancellationTokenSource(); 
     var token = _tokenSource.Token; 

     await Task.Run(() => 
     { 
      if (token.IsCancellationRequested) 
       return; 

      while (!token.IsCancellationRequested) 
      { 
       Dispatcher.Invoke(() => 
       { 
        double position = media.Position.TotalSeconds; 
        if (position >= Stop) 
         SetStartPosition(); 
       }); 
       Thread.Sleep(100); 
      } 
     }, token); 
    } 

    private void SetStartPosition() 
    { 
     media.Position = TimeSpan.FromSeconds(Start); 
    } 

    public double Start 
    { 
     get { return _start; } 
     set { _start = value; OnPropertyChanged(); SetStartPosition(); } 
    } 

    public double Stop 
    { 
     get { return _stop; } 
     set { _stop = value; OnPropertyChanged(); } 
    } 

    [NotifyPropertyChangedInvocator] 
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

MainWindow.xaml

<Window x:Class="WpfApplication1.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" 
     Title="MainWindow" 
     Height="422" 
     Width="450"> 
<Grid Margin="10"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="340" /> 
     <RowDefinition Height="*" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition /> 
     <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 

    <MediaElement Grid.Row="0" Grid.ColumnSpan="2" Margin="0,0,0,10" x:Name="media" /> 
    <TextBox Grid.Row="1" Grid.Column="0" Text="{Binding Start}"></TextBox> 
    <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Stop}"></TextBox> 
</Grid> 

enter image description here

+1

デリゲート 'async'と' await Task.Delay(TimeSpan.FromMilliseconds(100)) 'を代わりに作るのはどうですか?スレッドをブロックする理由は全くありません。 – kai

+0

真のdat、なぜではない –

+0

上記のコードは、ループのために正常に動作しています。しかし、AとBがユーザー入力であるA点からB点までビデオを再生したい場合はどうすればよいですか?この場合、ボットの開始時間と終了時間を同じに設定しようとしましたが、その場合は動作しません。 –

関連する問題