In my WPF application, the user presses a button to start a 3D model rotating smoothly, and lets up on the button to stop the rotation.
To do this, I create a DispatcherTimer:
DispatcherTimer timer = new DispatcherTimer();
timer.Tick += new EventHandler( timer_Tick );
timer.Interval = new TimeSpan( 0, 0, 0, 0, 30 );
And when the button is pressed I call timer.Start()
and when the button is let up I call timer.Stop()
.
The timer_Tick
function changes the rotation of the model:
void timer_Tick( object sender, EventArgs e )
{
spin = ( spin + 2 ) % 360;
AxisAngleRotation3D rotation = new AxisAngleRotation3D( new Vector3D( 0, 1, 0 ), spin );
Transform3D rotate = new RotateTransform3D( rotation );
model2.Transform = rotate;
}
What I notice is that the model spins smoothly for the most part, but often freezes and stutters, pausing for various durations, sometimes up to like 1/4 second.
Is there a way to make this smoother? I understand that by using DispatcherTimer (as opposed to, say, System.Timers.Timer) the callbacks happen on the UI thread. But it's necessary for me to be on the UI threat in order to run the line
model2.Transform = rotate;
I have read about various ways to get a timer callback on some other thread. But it seems like in the end I have to synchronize with the UI thread to call that line. If I use Invoke() to marshal from, say, the System.Timers.Timer callback thread to the UI thread, will that give an overall smoother animation? It seems like it shouldn't, since it's having to synchronize with the UI thread just like DispatcherTimer presumably does. And for that matter it seems like any scheme for setting model2.Transform
on a regular interval would be in the same boat with respect to the UI thread, no?
(As a perhaps secondary question, I'm trying to understand what's causing the pauses in the first place. As far as I can know, there's nothing else significant that the UI thread is doing. So I don't understand what's happening during those pauses. Garbage collection? It doesn't seem like there should be much garbage to collect, and it doesn't seem like the pause would be so extreme.)
Set a priority. The default is Background
, that might explain the stuttering you see. I think Render
is the level you want but do experiment.
DispatcherTimer timer = new DispatcherTimer(DispatcherPriority.Render);
If that isn't smooth enough you could try setting it up as an Animation.