When should one care about finishing one method before start next one?
Using C# in WPF, together with LINQ to SQL and LINQ for quering my generic collections, I noticed that sometimes, when I use several methods one after another and results of the first one are needed for next function, I should care about finishing actions of first function before starting next.
SomeMethod()
{
FirstMethod();
NextMethod();
....
}
Mostly it is related to methods, quering database, when updated results are used by next method.
Is it poss开发者_如何学运维ible to sum up when the possibility of "not yet updated for continuing" can take place in c# and how this issue is generally solved?
Unless you're doing multi-threading, it usually is not too hard to avoid the situation where you continue before you're ready. In most situations where you call a method or ask for data, your next instruction is not executed until the previous instruction is done or at least ready.
(For example, you can start using a DataReader it will return control to your code before it has all the data, but it still protects you from "getting ahead of yourself". it won't give you a false "end". If you use it faster than it gets the data, it will force your next instruction to wait rather than mess up your logic. And if you're defined Linq expression hasn't actually executed yet, it always will, in time, when you ask for its results.)
.Net protects you pretty well from asynchronous problems, unless you ask for them. If you're multi-threading, or triggering an external process (web service or something) somewhere else and then assuming instantly that it's finished and you can depend on its outcome, then you'll have problems. But in general, just code away.
It has sometimes been tricky for me dealing with asynchronous issues, but they have never really taken me by surprise.
This should only be an issue if a function you are calling is asynchronous or "non-blocking," which is unusual. Just check the documentation of the function. If you are explicitly using a thread or threads, use a join to ensure they finish execution. If you are using a function whose name starts with "Begin," call the next operation from the corresponding End. The last resort is using a loop and a Thread.Sleep(0); to force execution to wait for a certain condition to be true.
You always need to be aware of "side-effects" and "determinism" in your code. If the side-effect (i.e. what happens when the code runs) can have an impact on something else (inserting, deleting rows, creating objects, etc) you need to be aware of the order of completion and control when it happens.
You also need to be aware of the determinism of your code (i.e. can I know that this thing will be there when I need it), again if its in question you need to control how your code executes.
Take for example processing records from a database. You must have the records before you can process them, so you must do them in that order. If the two processes are in different locations in your code (threads, callbacks, events, etc). The second function (processing the records) must be made aware of the state of the first function (getting the rows) usually done with flags, locks, semaphores, etc.
For determinism think of guard statements in a function. If my function needs to have a string and a not null object, I first check those conditions when we enter the function before I start calling methods on those objects (calling string.ToLower() is fine on a string, but bad on a null object). In this way I am doing runtime determinism to prevent errors in my code (such as NullReference, etc). The compiler performs its own compile time determinism, but it cannot be aware of the state of objects during execution so it only does its comparisons on operations (whether they are semantically valid or not).
Normally NextMethod()
will execute just after FirstMethod()
returns.
However, as you're talking about WCF, it might be you are using asynchronous methods, although usually they should have Async
in their name, i.e. GetMonstersAsync(...)
.
In that case the methods indeed would be executed almost simultaneously.
Return values of asynchronous methods are handled in callback methods. You would place the call to the second method in the callback of the first one if you need to execute them in sequential order.
There's two ways of solving this:
Use a lock mechanism or redesign your methods to feed into each other, forcing one to execute first.
A lock mechanism can either be locking the thread until a worker process completes, or using a boolean value with a while loop:
while (locked)
{
// sleep or do something else
}
... rest of code
Refactoring your code would involve passing the value of one method into another method:
NextMethod(FirstMethod());
In order to force FirstMethod to finish.
精彩评论