I am currently experimenting with Godot C# making a basic shooter and for the gun's fire rate I have been experimenting with different delay systems. Node Timers work although I'm trying to make the script generic, and the Timer calls seem to only call functions in the parent script.
I'm now looking at C#'s Task.Delay method and it also seems to work, with it being an async action it does not look to be affected by the frame rate or slow down the game.
My question is, is there any known issue for using Task.Delay in game applications: like is it unreliable or can it crash if too many instances of the method are called?
Here's the code below although I don't think it’s important:
private void shoot() {
//if "canShoot" spawn bullet
ShootCooledDown();
}
private async void ShootCooledDown() {
TimeSpan span = TimeSpan.FromSeconds((double)(new decimal(shotDelay)));
canShoot = false;
await Task.Delay(span);
canShoot = true;
}
My question is, is there any known issue for using Task.Delay in game applications: like is it unreliable or can it crash if too many instances of the method are called?
Not per se. There is nothing in particular wrong with Task.Delay in games, nor too many instances of it.
However, what you are doing after Task.Delay can be a problem. If you execute await Task.Delay(span);, the code that comes after might run in a different thread, and thus it could cause a race condition. This is because of await, not because of Task.Delay.
For example, if after await Task.Delay(span); you will be adding a Node to the scene tree (e.g. a bullet), that will interfere with any other thread using the scene tree. And Godot will be using the scene tree every frame. A quick look at Thread-safe APIs will tell you that the scene tree is not thread-safe. By the way, the same happen with virtually any widget API out there.
The solution is use call_deferred (CallDeferred in C#) to interact with the scene tree. And, yes, that could offset the moment it happens to the next frame.
I'll give you a non threading alternative to do that.
There are method get_ticks_msec and get_ticks_usec (GetTicksMsec and GetTicksUsec in C#) on the OS class, that give you monotone time which you can use for time comparison.
So, if you make a queue with the times it should shoot (computed by taking the current time plus whatever interval you need). Then in your process or physics process callback, you can check the queue. Dequeue all the times that are overdue, and create those bullets.
If you don't want to solve this with Godot APIs, then start a Stopwatch at the start of the game, and use its elapsed time.
But perhaps that is not the mechanic you want anyway. If you want a good old cool-down, you can start the Stopwatch when you need the cool-down, and then compare the elapsed time with the cool-down duration you want to know if it is over.
I don't have any experience with Godot.. but my idea would be....
instead of using a timer, you could store the last shoottime in a variable/field. If you're trying to shoot within the lastTimeShot+coolDown, just ignore the shoot command.
For example:
private DateTime _lastShot = DateTime.MinValue;
private void shoot()
{
TimeSpan span = TimeSpan.FromSeconds((double)(new decimal(shotDelay)));
// if the time when the last shot has fire with the cooldown time
// is greater than the current time. You are still in the cooldown time.
if(_lastShot.Add(span) > DateTime.UtcNow)
return; // within cooldown, do nothing
//if "canShoot" spawn bullet
ShootCooledDown();
_lastShot = DateTime.UtcNow;
}
Due to a valid comment of Theodor, about changing the system time would lead bug-prone gameplay.
I wrote a second version.
private Stopwatch _shootingCooldownStopwatch = default;
private void shoot()
{
var shotDelayMs = shotDelay * 1000;
// if the _shootingCooldownStopwatch is ever started
// and the ElapsedMilliseconds are in the showDelay
// we're not allowed to fire again. So exit the method.
if (_shootingCooldownStopwatch?.ElapsedMilliseconds < shotDelayMs)
return;
_shootingCooldownStopwatch = Stopwatch.StartNew();
//if "canShoot" spawn bullet
ShootCooledDown();
}
I think this would be a better solution.
When you develop games in Godot or any other game engine, you shouldn't use any timer based in the computer clock, like the Stopwatch or Task.delay. Instead, you have to manage yourself the time elapsed using the delta time from the previous frame, which is received in the _Process(float delta) or _PhysicsProcess(float delta) methods. The reason are:
The time will be more accurate in case of frame-rate drop.
If you pause the game, timer will pause too.
That's the main reason Godot offers you a Timer component that you have to attach to the current scene in order to work with it.
If you don't want to add anything to the scene, which completely reasonable, you have to get the delta, storing the elapsed time in a variable and check if this variable reach some limit.
In my games, I use my own timers with this very simple class:
public class Timer {
public float Elapsed { get; private set; } = 0;
public bool Stopped { get; private set; } = true;
public float Alarm { get; private set; } = float.MaxValue;
public Timer Start() {
Stopped = false;
return this;
}
public Timer Stop() {
Stopped = true;
return this;
}
public Timer Reset() {
Elapsed = 0;
return this;
}
public Timer ClearAlarm() {
Alarm = float.MaxValue;
return this;
}
public Timer SetAlarm(float finish) {
Alarm = finish;
return this;
}
public bool IsAlarm() => Elapsed > Alarm;
public Timer Update(float delta) {
if (!Stopped) {
Elapsed += delta;
}
return this;
}
}
```
You have to Update the timer in every frame
I am no expert in Godot but I can tell that Task.Delay() is considered better than alternatives like Thread.Sleep() for example because being asynchronous i releases the thread to the thread pool and when the time has passed it continues execution, in contrast to the latter option that blocks the thread instead.
The problem I can see is that each web server can accept a max limit of concurrent requests, by using Task.Delay() in your code you can start accumulating requests "just waiting" due to the delay. So if your app starts receiving a big amount of requests coupled with a long Delay time that might be an issue with requests queued up (delay) or even denied.
If the delay is a number of seconds (significant time) then I would probably think about storing user in a cache (you can also store in a dictionary Dictionary<string, bool> where string is the userId but this solution will not scale out, that is why I suggest a distributed cache), and check (TryGetValue()) your cache if user is allowed to shoot. If delay is a couple of microseconds (affordable time) still not an ideal solution but it will probably be a problem.
In contrast to the answer by #Theraot and its approach via await Task.Delay(span) and according to my understanding, asynchronous does NOT equal to multi-threading. Using await Task.Delay(span) won't cause your code executing in another thread. So you don't really need to use CallDeferred in this case.
Reference:
What is the difference between asynchronous programming and multithreading?
Does Task delay create new Thread?
Does the use of async/await create a new thread?
Related
Does this work? This is in the start method, using photon for networking. I am trying to wait till room time is initialised.
Wait:
if (!PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey("StartTime") )
{
goto Wait;
}
else
{
goto Continue;
}
Continue:
startTime = double.Parse(PhotonNetwork.CurrentRoom.CustomProperties["StartTime"].ToString());
In general I would say avoid using goto at all!
In almost all cases I can think of any other solution in my eyes is cleaner and better to read and maintain than goto jumps. It is more a "relic" of former times. In the examples of goto might be the only use-case where it might make sense .. within a switch-case or to break out of a nested loop .. but even there you can find other (in my eyes better) solutions.
Your code basically equals writing
while(!PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey("StartTime")) { }
startTime = double.Parse(PhotonNetwork.CurrentRoom.CustomProperties["StartTime"].ToString());
And latest now I hope you see the huge issue: You have a neverending while loop!
Inside the while the condition is never changed
And it can not be changed from the outside either since you run this in Start so the entire Unity main thread is blocked until that loop ends. I'm not 100% sure but afaik PhotonNetwork needs the Unity main thread to dispatch the received events -> your condition probably will never ever become true.
You should rather use a Coroutine. A Coroutine is like a small temporary Update method. It is not async but rather runs right after Update until the next yield statement and thereby still allows your Unity main thread to continue rendering and doesn't freeze your entire application.
// Yes, if you make Start return IEnumerator
// then Unity automatically runs it as a Coroutine!
private IEnumerator Start ()
{
// https://docs.unity3d.com/ScriptReference/WaitUntil.html
// This basically does what it says: Wait until a condition is true
// In a Coroutine the yield basically tells Unity
// "pause" this routine, render this frame and continue from here in the next frame
yield return new WaitUntil(() => PhotonNetwork.CurrentRoom.CustomProperties.ContainsKey("StartTime"));
startTime = double.Parse(PhotonNetwork.CurrentRoom.CustomProperties["StartTime"].ToString());
....
}
Even better than checking this every frame in a loop at all would actually be
check this once in start
only check it again once after the room properties have actually changed
So something like e.g.
bool isInitialzed;
private void Start ()
{
TryGetStartTime (PhotonNetwork.CurrentRoom.CustomProperties);
}
private void TryGetStartTime(Hashtable properties)
{
if(!properties.Contains("StartTime")) return;
startTime = double.Parse(properties["StartTime"].ToString());
isInitialzed = true;
}
public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
{
TryGetStartTime (propertiesThatChanged);
}
And rather make other methods wait until isInitialized is true.
First of all, I know that Application.targetFrameRate exists, and it does a good enough job, but I want something more accurate. For me, it limits the frame rate to around 60.3 when set to 60, and around 204 when set to 200. Btw these are measured in builds (not in the editor) using RTSS 7.2.
So I set out to create my custom frame limiter in Unity using low level timers, but it just doesn't work correctly for some reason. Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System;
public class FrameLimiter : MonoBehaviour
{
private FrameLimiter m_Instance;
public FrameLimiter Instance { get { return m_Instance; } }
public double FPSLimit = 300.0;
private long lastTime = HighResolutionDateTime.UtcNow.Ticks;
void Awake()
{
m_Instance = this;
}
void OnDestroy()
{
m_Instance = null;
}
void Update()
{
if (FPSLimit == 0.0) return;
lastTime += TimeSpan.FromSeconds(1.0 / FPSLimit).Ticks;
var now = HighResolutionDateTime.UtcNow.Ticks;
if (now >= lastTime)
{
lastTime = now;
return;
}
else
{
SpinWait.SpinUntil(() => { return (HighResolutionDateTime.UtcNow.Ticks >= lastTime); });
}
}
}
Basically this is a singleton that's set to execute before any other script in the script execution order, and it blocks execution until the right time has been reached.
The way it works is it keeps track of the precise time when it last allowed a frame to be rendered (it obtains the current time from a very precise low level timer, here's more detail about that). Then in every call to its Update() function, it adds 1.0 / FPSLimit seconds to it to get the time when the next frame should be rendered, then if the current time is less than this time, it blocks execution until that timestamp has been reached.
SpinWait is basically just an efficient way to block execution without pinning the CPU like an empty while loop would. But just for the record, I did try an empty while loop too, and got the same results, except with much higher CPU usage.
So if you understand how this code is supposed to work, you should see that in theory this should lock the frame rate very precisely, especially given that this timer has a precision better than 1μs (0.001ms) according to Microsoft.
But despite all that, I get about 58.8 FPS when I set this to lock at 60, which I really don't understand. I'm running the build in exclusive full screen mode with V-sync disabled. Btw I'm getting way higher frame rates with no limiting, so the base performance of the game isn't the issue.
Any help would be appreciated!
The problem was weirder than I thought. It seems like this implementation of DateTime rounds the stored time internally to a whole number of milliseconds, so my frame limiter was pacing frames at 17ms instead of 16.6666ms when set to 60 FPS.
The solution was to alter the code for the timer I'm using, and just get the raw value returned by GetSystemTimePreciseAsFileTime() instead of encapsulating it in a DateTime object.
With this change, RTSS shows a perfect 60.0 FPS lock in the build, with occasional dips to 59.9, if the limiter is set to 60.
Here's what it looks like with a frametime graph as well. I was looking around the map at different things to try to excercise the frame limiter's consistency a bit. Safe to say, I made a much better frame limiter than Unity's own :)
If your program works perfectly and the spinwait finishes exactly at the calculated time you get exactly 60fps.
Nothing is perfect so it will take a bit more than the calculated time giving you a lower frame rate.
I'm writing a game with some animations, and use those animations when the user clicks on a button. I would like to show the user the animation, and not "just" call a new level with Application.loadLevel. I thought I could use the Time.DeltaTime in the onMouseUp method and add it to a predefined 0f value, then check if it is bigger than (for example) 1f, but it just won't work as the onMouseUp method adds just "it's own time" as the delta time.
My script looks like this now:
public class ClickScriptAnim : MonoBehaviour {
public Sprite pressedBtn;
public Sprite btn;
public GameObject target;
public string message;
public Transform mesh;
private bool inAnim = true;
private Animator animator;
private float inGameTime = 0f;
// Use this for initialization
void Start () {
animator = mesh.GetComponent<Animator>();
}
// Update is called once per frame
void Update () {
}
void OnMouseDown() {
animator.SetBool("callAnim", true);
}
void OnMouseUp() {
animator.SetBool("callAnim", false);
animator.SetBool("callGoAway", true);
float animTime = Time.deltaTime;
Debug.Log(inGameTime.ToString());
// I would like to put here something to wait some seconds
target.SendMessage(message, SendMessageOptions.RequireReceiver);
}
}
}
Im not entirely sure what your trying to do by using Time.deltaTime in onMouseUp. This is just the time in seconds since the last frame was rendered, and should act the same no matter where you try to access it. Normally it is used in a function that is called every frame, not one-off events like onMouseUp.
Despite not being certain what you are trying to achieve, it sounds like you should be using Invoke:
http://docs.unity3d.com/ScriptReference/MonoBehaviour.Invoke.html
Just put the code you wish to be delayed into a separate function, and then invoke that function with a delay in onMouseUp.
EDIT: To backup what some others have said here I would not use Thread.Sleep() in this instance.
You want to do this (and all waiting functions that do not appear to make the game "freeze") by blocking the Update loop by using a Coroutine.
Here is a sample of what you are probably looking for.
void OnMouseUp()
{
animator.SetBool("callAnim", false);
animator.SetBool("callGoAway", true);
//Removed the assignement of Time.deltaTime as it did nothing for you...
StartCoroutine(DelayedCoroutine());
}
IEnumerator DoSomethingAfterDelay()
{
yield return new WaitForSeconds(1f); // The parameter is the number of seconds to wait
target.SendMessage(message, SendMessageOptions.RequireReceiver);
}
Based on your example it is difficult to determine exactly what you want to accomplish but the above example is the "correct" way to do something after a delay in Unity 3D. If you wanted to delay your animation, simply place the calling code in the Coroutine as I did the SendMessage invocation.
The coroutine is launched on it's own special game loop that is somewhat concurrent to your game's Update loop. These are very useful for many different things and offer a type of "threading" (albeit not real threading).
NOTE:
Do NOT use Thread.Sleep() in Unity, it will literally freeze the game loop and could cause a crash if done at a bad time. Unity games run on a single thread that handles all of the lifecycle events (Awake(), Start(), Update(), etc...). Calling Thread.Sleep() will stop the execution of these events until it returns and is most likely NOT what you're looking for as it will appear that the game has frozen and cause a bad user experience.
I searched a few links for Timer Control for both Windows and WPF applications but I would appreciate some advice on my situation...
As I'm using WPF it seems initial options are either System.Windows.Threading.DispatcherTimer or System.Diagnostics.Stopwatch
What I need to achieve is for each WPF DocumentPanel to request an update from an external API at a defined interval between typically 100ms Min - anytime Max with the interval unique to each DocumentPanel. Eg DP1 could be 100ms, DP2 could be 20,000ms etc.
Normally my app would start with 1 DocumentPanel but the user can expand panels without limit so it's the users judgement on CPU ability and speed of app.
Criteria include:
Multiple DocumentPanels - Typically 1 - 20 minimum but any advice on scalability is welcome.
Variable event interval (Iv) (Minimum event interval 100ms - Max < 1day)
Accuracy - 1ms (cannot have interval below (Iv)ms under ANY circumstances, over is not as much concern but needs to be be within several ms) EDIT: 1ms is not strictly a requirement but average (Iv) must be maintained over a short timescale.
Each DocumentPanel must display live date/time but produce events based on set interval
I'm really after help with design consideration rather than actual code at the moment as WPF is confusing matters for me.
Currently, I'm verging towards using a single instance of System.Diagnostics.Stopwatch and allow each panel to act on the stopwatch event whether the interval time has been reached.
Can anyone advise?
Thank you
O
its better to use just one System.Windows.Threading.DispatcherTimer with 100ms as ticks, then use Tags to determine its own interval, for example you can use
struct IntervalComparer
{
int myinterval; //the individual update interval (300ms for example)
int currentinterval;
public IntervalComparer(int myinterval)
{
this.myinterval=myinterval;
this.currentinterval=0;
}
public void TickMe()
{
currentinterval++;
}
public void ResetkMe()
{
currentinterval = 0;
}
public bool CanIUpdate()
{
return myinterval == currentinterval;
}
}
on the creation
.... Form_Loaded....
{
.....
mypanel=new Panel();
mypanel.Tag= new IntervalComparer(2); // 2 * 100ms
.....
}
.... Timer_Tick....
{
....
(mypanel.Tag as IntervalComparer).TickMe();
if((mypanel.Tag as IntervalComparer).CanIUpdate())
{
UpdateMyPanel();//your update method
(mypanel.Tag as IntervalComparer).ResetMe();
}
....
}
Generally in a case like this I would have a single timer which when then check for the elapsed time for each DocumentPanel. I'm guessing 100% accuracy is not critical, if they select 999ms then they won't notice if you main timer fires every 50ms so can only give them increments of 50ms. Windows does not give that sort of accuracy anyway, I learnt this when trying to trigger a flash once.
I've used the following approach to achieve something similar in a Silverlight app:
Single timer which ticks at a small interval (you're discretion, but would need to be lower than the lowest supported update interval), and then have each DocumentPanel subscribe to this timer's tick event.
When the tick event is fired, each DocumentPanel would then determine if an update is required based on it's update frequency (E.G. (last update - now ) > interval).
There's a comparison of some timer classes here:
http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
DispatcherTimer isn't mentioned, but the important difference between DispatcherTimer and System.Timers.Timer is:
If a System.Timers.Timer is used in a WPF application, it is worth
noting that the System.Timers.Timer runs on a different thread then
the user interface (UI) thread. In order to access objects on the user
interface (UI) thread, it is necessary to post the operation onto the
Dispatcher of the user interface (UI) thread using Invoke or
BeginInvoke. Reasons for using a DispatcherTimer opposed to a
System.Timers.Timer are that the DispatcherTimer runs on the same
thread as the Dispatcher and a DispatcherPriority can be set on the
DispatcherTimer.
(from http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer.aspx).
Without knowing how you are currently handling UI updates and how you're program is structured, it's hard to say which timer you should use.
I'm not hugely familiar with the using the StopWatch, but my opinion is (after reading http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx) that using a single StopWatch isn't something that is particularly suited to this problem
use can inherit from DocumentPanel if you need the Tag property & for more encapsulation
class UpdatableDocumentPanel : DocumentPanel
{
public int myinterval { get; set; }//the individual update interval (300ms for example)
int currentinterval;
public void Update()
{
currentinterval++;
if (myinterval == currentinterval)
{
currentinterval = 0;
UpdateMyPanelMethod();
}
}
}
and
.... Form_Loaded....
{
.....
mypanel.myinterval = 2; // 2 * 100ms
.....
}
.... Timer_Tick....
{
....
mypanel.Update(); // simply
....
}
I want a method in a DrawableGameComponent class to not return until a particular condition is met
Say I have this class (snippet from a DrawableGameComponent class):
public override void Update(GameTime gameTime)
{
if (moving && pixFromLastMove <= distanceToMove)
{
position += velocity;
pixFromLastMove += velocity.Length();
}
else
{
moving = false;
}
if (rotating)
{
rotation += 0.1f;
var cRotation = MathHelper.Clamp(rotation, -MathHelper.PiOver2, angleBeforeRotation + degToRotate);
if (cRotation != rotation)
{
rotation = cRotation;
angleBeforeRotation = rotation;
rotating = false;
}
}
base.Update(gameTime);
}
public void Ahead(int pix)
{
moving = true;
distanceToMove = pix;
pixFromLastMove = 0;
velocity = new Vector2((float) Math.Cos(rotation), (float) Math.Sin(rotation))*5.0f;
//DO NOT RETURN UNTIL THIS ROBOT HAS MOVED TO ITS DESTINATION
}
public void TurnLeft(int deg)
{
rotating = true;
degToRotate = MathHelper.ToRadians(deg);
angleBeforeRotation = rotation;
//DO NOT RETURN UNTIL THIS ROBOT HAS BEEN FULLY ROTATED
}
This class is being drawn (Draw())in the main thread (because this drawablegamecomponent is executing in seperate thread), and also in the main thread I have a list of commands that I want to be executed in order...but currently, since the Ahead method returns just after assigning a value to velocity, the methods will run almost concurrently, which in turn just executes all the animations at the same time.
So what do you think should I do to prevent methods that are commands (Ahead,TurnLeft etc..) from returning before a certain condition is met?
You need to create some kind of state machine for your Update() method. e.g.
public override void Update() {
if (movingRobot) {
OnlyUpdateRobotPosition();
}
else {
DoStuffPerhapsIncludingStartingRobotMove();
}
}
Or am I missing the question?
Ahh, two words: Cooperative multitasking. With the joy of Fibers (or your cooperative multitasking building block of choice) you could (after laying some ground work, such as this to enable fibers in C#) do something like this:
public void Ahead(int pix)
{
moving = true;
distanceToMove = pix;
pixFromLastMove = 0;
velocity = new Vector2((float) Math.Cos(rotation), (float) Math.Sin(rotation))*5.0f;
//DO NOT RETURN UNTIL THIS ROBOT HAS MOVED TO ITS DESTINATION
while(!HasReachedDestination())
{
Yield(); // let another fiber run
}
}
In order to make this work however you need to implement a simple round-robin scheduler. C# isn't really my boat, but what I'd do is to keep it simple and create some sort of base-class that I'd call Cooperative (or something). This class would have a static list of all created fibers as well as the static methods Create() and Yield(). Create() will create a new fiber (or whatever) and Yield() will simply schedule next fiber to execute (round-robin style), in fiber-world that would include a call to SwitchToFiber(). It will also have a virtual method called Start() (or whatever) that is where the fiber will start to run.
To make it more fancy-smancy you could later keep separate lists of fibers that are either runnable or not runnable (i.e. waiting for something to happen). In that case you might be able to simplify the loop in Ahead to:
WaitFor(HasReachedDestination);
But I suggest getting your feet wet with the concept of cooperative multitasking first.
Finally some thoughts on what should be made fibers, typically your main update loop is one fiber, updating and drawing all objects and then calls Yield(). The all game objects would also be fibers (this may not be feasible if you have a lot of game objects). For your game objects you'd do something like:
public override Start()
{
do
{
if(EnemyToTheLeft())
{
TurnLeft(90); // this will call Yield and return when we have finished turning
Shoot();
}
Yield(); // always yield
}while(!dead);
}
I agree with Pop Catalin: it is probably best not to block in those command functions. I think you could improve your game by thinking about the design a bit more. Let me provide some thoughts for you on how you could possibly improve your design.
First, it sounds like the problem you are describing is that you want to send a lot of move commands, in a certain order, to a game component and have it execute those commands in that certain order. As you have noticed, there is a difference in the time it takes the computer to perform the calculations (for the velocity or rotation) and the time it takes the component to actually perform the action (move or rotate).
The problem with blocking during the calculations (Ahead, TurnLeft, etc) is that the update loop that is calling that function cannot update any other components. That may work okay if there is only one component to worry about, but that's not usually the case in most games.
Now for the good part: how do we fix this problem? I think erikkallen has the right idea, but I would take it a bit further. It sounds like the game component is some kind of entity that will be moving around, so why not give it an action queue? A simple implementation would be to just have your calling function call something like:
gameComponent.queueAction( (MethodInvoker)delegate()
{ gameComponent.Ahead(10); });
Your queueAction function might look like this:
public void queueAction(MethodInvoker action)
{
queue.Enqueue(action);
}
At the top of your Update function you could add:
if(noCurrentAction && queue.Count > 0)
{
((MethodInvoker)queue.Dequeue()).Invoke();
noCurrentAction = false;
}
And you'd need to add a line at the end of the Update function like:
if(!moving && !rotating)
noCurrentAction = true;
Now, I definitely wouldn't call this the best solution, but it doesn't take much code to implement it. Of course if you need to move and rotate at the same time you'll have to tweak it a bit. It will also get messier when you add different types of actions.
For a more general solution, I would think about making a base Action class, and deriving specific action classes from it. Then you could just push actions to the queue, and your Update function could call the action's Update function, which would do the work the two sections of your game components Update function is doing now.
These are just some ideas to think about, I hope something here will get you started.
One last thing I wanted to mention was that I don't see you using gameTime variable that is passed to Update. The amount your component moves and rotates may need to be a function of the elapsed time since Update was last called. Meaning that the Update function would move and rotate your game component based on the amount of time that has passed, not just how many times the Update function was called. I'm not very good at explaining it, and it depends on how you'd like your game to function. Here are a couple different posts from Shawn Hargreaves (XNA expert). Also, an XNA Forum post discussing the point I was trying to make.
Although I find your design somewhat odd, best way to accomplish what you want is to use an EventWaitHandle and signal it from another thread.
Say you have an instance of the waithandle on your class
you can call waithadle.WaitOne() in your method, and signal the even from another thread using waithandle.Set() when the condition is met, at which point your method will resume from waiting.