C# 在另一个线程中每0.5秒旋转一次图像
我想制作一个小命运之轮游戏,但我在制作一个旋转图像的事件时遇到了问题 这是我现在拥有的代码,但它似乎只运行了一次_线程C# 在另一个线程中每0.5秒旋转一次图像,c#,wpf,user-interface,C#,Wpf,User Interface,我想制作一个小命运之轮游戏,但我在制作一个旋转图像的事件时遇到了问题 这是我现在拥有的代码,但它似乎只运行了一次_线程 private readonly Timer _timer; private Thread _thread; private int _angle; public MainWindow() { InitializeComponent(); _timer = new Timer(500);
private readonly Timer _timer;
private Thread _thread;
private int _angle;
public MainWindow()
{
InitializeComponent();
_timer = new Timer(500);
_timer.Elapsed += RotateWheelEvent;
_timer.Start();
_angle = 0;
SetupRotationThread();
_thread.Start();
}
public void RotateWheelEvent(object sender, EventArgs args)
{
_thread.Abort();
_angle = _angle + 15;
_thread.Start();
}
public void SetupRotationThread()
{
var rotatetransform = new RotateTransform(_angle);
_thread = new Thread(
delegate()
{
ImageWheel.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.SystemIdle,
TimeSpan.FromSeconds(1),
new Action(
delegate()
{
ImageWheel.RenderTransformOrigin = new Point(0.5, 0.5);
ImageWheel.RenderTransform = rotatetransform;
}
));
});
}
您可以使用
System.Threading.Timer
而不是System.Timer
每次生成一个新的thraed
private System.Threading.Timer _timer;
private int _angle;
public MainWindow()
{
InitializeComponent();
_timer = new System.Threading.Timer((o) =>
{
_angle += 15;
Dispatcher.Invoke(DispatcherPriority.Background, (Action)delegate
{
ImageWheel.RenderTransformOrigin = new Point(0.5, 0.5);
ImageWheel.RenderTransform = new RotateTransform(_angle);
});
}, null, 500, 500);
}
然而,现在还不清楚你为什么要处理这个问题,你似乎在启动一个线程,这个线程只是将代码调用回UI线程,我看不出这个线程需要做什么工作
所以我想你需要的就是这个
private readonly Timer _timer;
private int _angle;
public MainWindow()
{
InitializeComponent();
_timer = new Timer(500);
_timer.Elapsed += RotateWheelEvent;
_timer.Start();
_angle = 0;
}
public void RotateWheelEvent(object sender, EventArgs args)
{
Dispatcher.Invoke(DispatcherPriority.Background, (Action)delegate
{
_angle += 15;
ImageWheel.RenderTransformOrigin = new Point(0.5, 0.5);
ImageWheel.RenderTransform = new RotateTransform(_angle);
});
}
您可以使用
System.Threading.Timer
而不是System.Timer
每次生成一个新的thraed
private System.Threading.Timer _timer;
private int _angle;
public MainWindow()
{
InitializeComponent();
_timer = new System.Threading.Timer((o) =>
{
_angle += 15;
Dispatcher.Invoke(DispatcherPriority.Background, (Action)delegate
{
ImageWheel.RenderTransformOrigin = new Point(0.5, 0.5);
ImageWheel.RenderTransform = new RotateTransform(_angle);
});
}, null, 500, 500);
}
然而,现在还不清楚你为什么要处理这个问题,你似乎在启动一个线程,这个线程只是将代码调用回UI线程,我看不出这个线程需要做什么工作
所以我想你需要的就是这个
private readonly Timer _timer;
private int _angle;
public MainWindow()
{
InitializeComponent();
_timer = new Timer(500);
_timer.Elapsed += RotateWheelEvent;
_timer.Start();
_angle = 0;
}
public void RotateWheelEvent(object sender, EventArgs args)
{
Dispatcher.Invoke(DispatcherPriority.Background, (Action)delegate
{
_angle += 15;
ImageWheel.RenderTransformOrigin = new Point(0.5, 0.5);
ImageWheel.RenderTransform = new RotateTransform(_angle);
});
}
最坏的情况下,您应该在代码隐藏中使用
Dispatchermer
:
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(0.5)
};
timer.Tick += (s, e) => ((RotateTransform)ImageWheel.RenderTransform).Angle += 15;
timer.IsEnabled = true;
但实际上根本没有必要这么做。您只需在XAML中设置一个情节提要
。比如:
<Image x:Name="image" RenderTransformOrigin="0.5,0.5" ...>
<Image.RenderTransform>
<RotateTransform/>
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard Duration="00:00:00.5" RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="image" Storyboard.TargetProperty="(Image.RenderTransform).(RotateTransform.Angle)" By="15"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
其中一些语法可能不太正确(在linux上,因此无法检查),但您已经明白了。你把一些非常简单的事情弄得太复杂了。最坏的情况是,你应该在你的代码隐藏中使用一个
分派器:
var timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(0.5)
};
timer.Tick += (s, e) => ((RotateTransform)ImageWheel.RenderTransform).Angle += 15;
timer.IsEnabled = true;
但实际上根本没有必要这么做。您只需在XAML中设置一个情节提要
。比如:
<Image x:Name="image" RenderTransformOrigin="0.5,0.5" ...>
<Image.RenderTransform>
<RotateTransform/>
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard Duration="00:00:00.5" RepeatBehavior="Forever">
<DoubleAnimation Storyboard.TargetName="image" Storyboard.TargetProperty="(Image.RenderTransform).(RotateTransform.Angle)" By="15"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
其中一些语法可能不太正确(在linux上,因此无法检查),但您已经明白了。你把一些非常简单的东西弄得太复杂了。为什么要穿这个?我不需要这样做,让它每隔一段时间旋转一次吗?你不需要一个新的线程,只需要一个每天运行的计时器500ms@sa_ddam213在.NET中没有,在函数返回之前,窗口不会刷新。您无法启动调用的线程<代码>中止
“线程通常也是一种不好的做法。你为什么要执行此操作?我不需要这样做以使它每隔一段时间旋转一次吗?你不需要一个新线程,只需要一个每天运行的计时器500ms@sa_ddam213在.NET中没有,在函数返回之前,窗口不会刷新。您无法启动调用的线程<代码>中止'ing线程通常也是一种不好的做法。您正在使用计时器(使用一个线程)来使用调度程序,这有什么意义?同意J.列侬的观点。计时器在线程池线程上滴答作响,此时您正在编组回UI线程。那只是不必要的开销。这正是分派器
有用的地方。我不确定OP为什么使用系统。计时器
,可能有一个原因我不知道,我关心的只是在每个勾号事件中启动一个新线程,我认为,如果OP在滴答声事件中没有执行和其他耗时的逻辑,最好使用dispatchertimer
或情节提要
。您使用的是计时器(使用一个线程)来使用调度程序,这有什么意义?同意J.列侬的观点。计时器在线程池线程上滴答作响,此时您正在编组回UI线程。那只是不必要的开销。这正是分派器
有用的地方。我不确定OP为什么使用系统。计时器
,可能有一个原因我不知道,我关心的只是在每个勾号事件中启动一个新线程,我认为,如果OP在滴答声事件中没有执行和其他耗时的逻辑,则dispatchertimer
或情节提要
将是最佳选择。