这只是我正在尝试做的简化版本
public partial class MainWindow : Window
{
private CancellationTokenSource tokenSource = new CancellationTokenSource();
public MainWindow()
{
InitializeComponent();
PrintButtonText("None");
}
private void PrintButtonText(string buttonText)
{
Console.WriteLine("Update!");
Task.Factory.StartNew(() =>
{
while (!tokenSource.Token.IsCancellationRequested)
{
Console.WriteLine("Button Pressed Text: " + buttonText);
}
}, tokenSource.Token);
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
tokenSource.Cancel();
PrintButtonText("Button1");
}
private void Button2_Click(object sender, RoutedEventArgs e)
{
tokenSource.Cancel();
PrintButtonText("Button2");
}
}
我做完
tokenSource.Cancel();
PrintButtonText("Button1");
它无法再次启动任务并继续打印我的行。我需要它以这种方式为我的程序工作。
我想停止线程并使用一些不同的参数重新启动它。我该如何实现?谢谢
编辑:
由于我没有获得简化版本的解决方案,因此这里有完整的代码以及我想做的事情。基本上,在wpf窗口上,摄影机渲染从启动开始。有一个按钮可以开始保存到文件,但是要保存,我必须更新配置并再次启动“管道”。
public partial class MainWindow : Window
{
private Pipeline pipeline = new Pipeline(); // Create and config the pipeline to sream color and depth frames.
private CancellationTokenSource tokenSource = new CancellationTokenSource();
private bool saveDataToFile = false;
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Config cfg = SetupConfig(false);
PipelineProfile pp = pipeline.Start(cfg);
StartRenderFrames(pp);
}
private void StartRenderFrames(PipelineProfile pp)
{
Colorizer colorizer = new Colorizer(); // The colorizer processing block used to visualize the depth frames.
// Allocate bitmaps for rendring. Since the sample aligns the depth frames to the color frames, both of the images will have the color resolution
using (var p = pp.GetStream(Stream.Color) as VideoStreamProfile)
{
imgColor.Source = new WriteableBitmap(p.Width, p.Height, 96d, 96d, PixelFormats.Rgb24, null);
imgDepth.Source = new WriteableBitmap(p.Width, p.Height, 96d, 96d, PixelFormats.Rgb24, null);
}
Action<VideoFrame> updateColor = UpdateImage(imgColor);
Action<VideoFrame> updateDepth = UpdateImage(imgDepth);
Task.Factory.StartNew(() =>
{
while (!tokenSource.Token.IsCancellationRequested)
{
// Wait for the next available FrameSet
using (var frames = pipeline.WaitForFrames())
{
var colorFrame = frames.ColorFrame.DisposeWith(frames);
var depthFrame = frames.DepthFrame.DisposeWith(frames);
// We colorize the depth frame for visualization purposes, .
var colorizedDepth = colorizer.Process(depthFrame).DisposeWith(frames);
// Render the frames.
Dispatcher.Invoke(DispatcherPriority.Render, updateDepth, colorizedDepth);
Dispatcher.Invoke(DispatcherPriority.Render, updateColor, colorFrame);
}
}
}, tokenSource.Token);
}
private Config SetupConfig(bool saveDepthFile)
{
Config cfg = new Config();
cfg.EnableStream(Stream.Depth, 640, 480, framerate: 15);
cfg.EnableStream(Stream.Color, 640, 480, format: Format.Rgb8, framerate: 15);
if (saveDepthFile)
{
cfg.EnableRecordToFile(@"C:\temp\My_test111.bag");
}
return cfg;
}
static Action<VideoFrame> UpdateImage(Image img)
{
var wbmp = img.Source as WriteableBitmap;
return new Action<VideoFrame>(frame =>
{
using (frame)
{
var rect = new Int32Rect(0, 0, frame.Width, frame.Height);
wbmp.WritePixels(rect, frame.Data, frame.Stride * frame.Height, frame.Stride);
}
});
}
private void StartSaving_Button_Click(object sender, RoutedEventArgs e)
{
tokenSource.Cancel();
pipeline.Stop();
// This is where I have a problem. Rendering thread does not stop before I want to start again.
Config cfg = SetupConfig(true);
PipelineProfile pp = pipeline.Start(cfg);
StartRenderFrames(pp);
}
}
答案 0 :(得分:0)
您应该使用Microsoft的Reactive Framework(又名Rx)-NuGet System.Reactive.Windows.Forms
并添加using System.Reactive.Linq;
-然后您可以执行以下操作:
private void Form1_Load(object sender, EventArgs e)
{
IObservable<string> button1Clicks =
Observable
.FromEventPattern<EventHandler, EventArgs>(h => button1.Click += h, h => button1.Click -= h)
.Select(ep => "Button1");
IObservable<string> button2Clicks =
Observable
.FromEventPattern<EventHandler, EventArgs>(h => button2.Click += h, h => button2.Click -= h)
.Select(ep => "Button2");
IDisposable subscription =
button1Clicks
.Merge(button2Clicks)
.StartWith("None")
.Select(x => Observable.Timer(TimeSpan.Zero, TimeSpan.FromMilliseconds(500.0)).Select(n => x))
.Switch()
.ObserveOn(this)
.Subscribe(x => Console.WriteLine(x));
}
这就是完成您想要的工作所需的全部代码。
您唯一需要做的就是将subscription
移到private
字段中,然后只需调用subscription.Dispose()
将其关闭。
这比弄乱取消令牌要简单得多。