Answer the question
In order to leave comments, you need to log in
Why can't I synchronize an async method?
Good day to all!
I have the following task. It is necessary to give change in coins to the user through the issuing devices. The problem is that devices can blunt and not give out the full amount. To do this, I planned to use the following algorithm:
1) issue a command to issue N coins
2) receive an asynchronous response about the issue of N coins (there is a corresponding callback #1) or receive an error message with a code and text (already another callback #2);
3) request the total number of issued coins (here he (the hopper) cannot lie) and writes how much he issued - M. The result also comes asynchronously to the corresponding callback #3. Need to wait for a response.
4) Compare M and N, if not equal, go to step 1, but replacing N with NM, if equal, go to the next hopper or to the screen with the result.
So, the crux of the problem.
My COHopper class has the following method:
internal bool DispenseCoins(int numberOfCoins)
{
if (!IsInited) return false;
var methodName = MethodBase.GetCurrentMethod().Name;
Logger.Fatal("Вызван {0} c параметром numberOfCoins={1}", methodName, numberOfCoins);
try
{
var loop = true;
var coinsCount = numberOfCoins;
if(coinsCount==0)return true;
while (loop)
{
if (DispenseCoinsWithCount(coinsCount))
{
Logger.Trace("Перед SendDispenseCoinsSendDispenseCoins");
while (SendDispenseCoins)
{
Thread.Sleep(100);
}
Logger.Trace("После coinsToGivePair.Key.SendDispenseCoins");
}
else Logger.Trace("DispenseCoinsWithCount - {0}", "False");
if (GetInfoAboutAllCountOfCoins())
{
Logger.Trace("Перед SendDispenseAllCoins");
while (SendDispenseAllCoins)
{
Thread.Sleep(100);
}
Logger.Trace("После SendDispenseAllCoins");
}
else Logger.Trace("GetInfoAboutAllCountOfCoins - {0}", "False");
if (LastCoinsDeliveryInfo == numberOfCoins)
loop = false;
coinsCount = numberOfCoins - LastCoinsDeliveryInfo;
}
return true;
}
catch (Exception e)
{
Logger.Fatal("{0} - {1}:{2}", methodName, MessageResource.ErrorUnExpectedException, e.Message);
return false;
}
}
Answer the question
In order to leave comments, you need to log in
If we are talking about multithreading, use synchronization objects (for example, ManualResetEvent) to synchronize threads. Then there is no need to fence this whole idea with callbacks
and this miserable code
while (SendDispenseAllCoins)
{
Thread.Sleep(100);
}
Replace
if (LastCoinsDeliveryInfo == numberOfCoins)
loop = false;
coinsCount = numberOfCoins - LastCoinsDeliveryInfo;
if (LastCoinsDeliveryInfo == coinsCount)
loop = false;
coinsCount -= LastCoinsDeliveryInfo;
LastCoinsDeliveryInfo
contains only the number of coins issued last. SendDispenseCoins
In addition to being inefficient , changing fields asynchronously SendDispenseAllCoins
may not work: the main thread may simply not see the changes made by another thread.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question