C# 在循环过程中按下捕捉按钮
我有一个WPF应用程序,它使用C# 在循环过程中按下捕捉按钮,c#,wpf,C#,Wpf,我有一个WPF应用程序,它使用MediaElement。 我想循环视频的某个部分。我有一个StartTime和EndTime变量用于循环。为了循环,我尝试了dispatchermer,但是对于小于1秒的循环来说,它太慢了。所以我尝试了简单的while循环,如下所示 while (true) { if(!buttonPressed) { while (mePlayer.Position < loop.EndTime) ; //go till end o
MediaElement
。
我想循环视频的某个部分。我有一个StartTime
和EndTime
变量用于循环。为了循环,我尝试了dispatchermer
,但是对于小于1秒的循环来说,它太慢了。所以我尝试了简单的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
}
}
while(true)
{
如果(!按钮按下)
{
while(mePlayer.Position
使用上述代码,即使是0.5秒的视频循环也可以正常运行,但是
上述方法的问题是,一旦它进入无限循环,它就无法检测到按钮按下,因此我无法停止循环。因此,我的问题是,如何检测while循环中的按钮按下,以便我停止循环视频并继续执行其他任务?我很惊讶您无法获得有关视频播放进度的任何信息。但是您可以通过组合
任务
和调度程序
(因为跨线程)来解决这个问题,而不阻塞UI,如下所示
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));
}
}
main window.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>
为什么不捕获事件/检测绑定属性中的更改,而不是循环?我没有检查,但肯定玩家有位置更改事件或类似的事件。我只是检查了一下,没有发现任何位置更改事件。为什么不让代理
异步
和等待任务。延迟(TimeSpan.frommissions(100))
?根本没有理由阻止线程。上面的代码在循环中运行良好。但是如果我想从A点到B点播放视频,A点和B点是用户输入,该怎么办呢。在本例中,我尝试将bot开始时间和结束时间设置为相同,但在这种情况下不起作用。工作正常,我更新了代码。请注意,您需要对“真实生活”应用程序进行一些修改。现在运行良好。谢谢Mikko Viitala。