"...because this call is not awaited" - c#

using System;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace Rohan.Gateway
{
public class Player
{
private PlayerSocket _mapSocket;
private PlayerSocket _clientSocket;
public int _characterId = -1;
public int _characterType = -1;
public string _characterName = "";
public int _playerId = -1;
public string _dumpFolder = "";
public int _packetIndex;
public PlayerSocket mapSocket
{
get { return this._mapSocket; }
}
public PlayerSocket clientSocket
{
get { return this._clientSocket; }
}
public bool isConnected
{
get { return this._mapSocket.isConnected && this._clientSocket.isConnected; }
}
public Player(Socket clientSocket)
{
this._clientSocket = new PlayerSocket(clientSocket, this, PlayerSocketType.Client);
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
socket.Connect(TCPListenerEx.remoteAddress, 22100);
this._mapSocket = new PlayerSocket(socket, this, PlayerSocketType.MapServer);
this.ValidateConnection();
}
public bool ValidateConnection()
{
if (!this.isConnected)
{
this.Disconnect();
return false;
}
return true;
}
public void Disconnect()
{
this._mapSocket.Disconnect();
this._clientSocket.Disconnect();
}
public void ReceiveClientData()
{
if (this.ValidateConnection())
{
this._clientSocket.ReceiveAsync();
}
}
public void DispatchClientData()
{
if (this.ValidateConnection())
{
this._mapSocket.SendAsync(this._clientSocket.reader);
}
}
public void ReceiveMapserverData()
{
if (this.ValidateConnection())
{
this._mapSocket.ReceiveAsync();
}
}
public void DispatchMapserverData()
{
if (this.ValidateConnection())
{
this._clientSocket.SendAsync(this._mapSocket.reader);
}
}
}
}
On the lines below, I get this warning
because this call is not awaited
public void ReceiveClientData()
{
if (this.ValidateConnection())
{
this._clientSocket.ReceiveAsync();
}
}
public void DispatchClientData()
{
if (this.ValidateConnection())
{
this._mapSocket.SendAsync(this._clientSocket.reader);
}
}
public void ReceiveMapserverData()
{
if (this.ValidateConnection())
{
this._mapSocket.ReceiveAsync();
}
}
public void DispatchMapserverData()
{
if (this.ValidateConnection())
{
this._clientSocket.SendAsync(this._mapSocket.reader);
}
}
Why am I getting this error?

In response to the comment asking:
Have you tried adding async to the signature then use await for the call of the method
You answered:
Yes, i did it already
But none of the code you posted shows this. And this is in fact the right way to correct this warning message.
Without a good Minimal, Complete, and Verifiable example that shows clearly all of the relevant types (including the PlayerSocket type and how these methods are being called) it's impossible to say for sure how you should fix your code. Your options include:
Disable the warning with the #pragma warning directive
Implicitly suppress the warning by assigning the returned Task object from each ...Async() method to a local variable. E.g.:
public void ReceiveClientData()
{
if (this.ValidateConnection())
{
var _ = this._clientSocket.ReceiveAsync();
}
}
Call the asynchronous operation synchronously. E.g.:
public void ReceiveClientData()
{
if (this.ValidateConnection())
{
this._clientSocket.ReceiveAsync().Wait();
}
}
Correctly await the asynchronous operation. This is, frankly, by far the best choice but will be the most complicated. Primary advantage is that you get the benefit of asynchronous operation (i.e. the code doesn't block waiting for the operation to complete), but you will still be able to observe any exception that might occur. Primary disadvantage is that you will have to change each method from void to async Task, and then effect the same change to each method's caller. And each caller of those callers, and so on, until you get to the top of the call stack for the thread.
Personally, I would strongly recommend the third or (especially) the fourth option. They are the only options that allow you to add try/catch to observe exceptions. There are some scenarios where the first and second options might make sense, but I would not say that doing socket I/O would be one of those scenarios.
There are a number of existing Stack Overflow questions and answers that go into more detail as to how to deal with this sort of thing. Please decide which approach you want to use, do some research, and if you have a specific issue, post a question that includes a good code example, so that an appropriate answer can be provided.

Related

How to substitute an event-based class for an observable-based class in C# and System.Reactive?

I have a class which has some events. At present, I decide to shift towards "Observables" since the benefits they propose. To reach this goal, I introduced an Observable property to be replaced with one of the events. Next, I made the event "private" to restrict its accessibility from out of the class. The event is invoked inside the class with a function when it is needed. However, I think It may be a better way to do this job. What is the proper practice? By the way, I am a novice in "System.Reactive," so if I have a misunderstanding with the concept, please clarify the matter. My code is below:
public class MyClass
{
public MyClass()
{
InformationSenderObservable=Observable.FromEventPattern<SolutionEventArg>(ev =>InformationSender += ev, ev => InformationSender -= ev);
}
private event EventHandler<SolutionEventArg> InformationSender;
public IObservable<EventPattern<SolutionEventArg>> InformationSenderObservable { get; }
internal void DoSomething()
{
// long calculation
SendInformation();
}
private void SendInformation()
{
InformationSender?.Invoke(this,new SolutionEventArg()
{
InfoProxyData = GetDetailsForBestCompressedData(),
ParallelProcess = parallelProcessing
});
}
}
Thanks to Theodor Zoulias, I finally understood how I could better handle my class. I used ISubject<T> instead of events in my class to send information from my class to another class subscribing to the ISubject<T>.
public class MyClass
{
public MyClass()
{
InformationSenderObservable=new Subject<SolutionEventArg>();
}
public ISubject<SolutionEventArg> InformationSenderObservable { get; }
internal void DoSomething()
{
// long calculation
SendInformation();
}
private void SendInformation()
{
try
{
InformationSenderObservable.OnNext(new SolutionEventArg()
{
InfoProxyData = GetDetailsForBestCompressedData(),
ParallelProcess = parallelProcessing
});
}
catch (Exception e)
{
InformationSenderObservable.OnError(e);
}
}
}
ISubject<T> implements both IObservable<T> and IObserver<T> simultaneously.

Call multiple methods in a defined order

Picture a case like this:
I have a controller action (or service method) where I need to call three methods in a consecutive order, each method has a single responsibility.
public return_type MyMethod(_params_) {
// .. some code
Method_1 (...);
Method_2 (...);
Method_3 (...);
// ... some more code
}
A developer can make the mistake of calling Method_2 before Method_1, or at least we can say that nothing forces him to follow this order, or to get an exception when the order isn't followed.
Now we can call Method_2 inside Method_1, and Method_3 inside Method_2, but that doesn't seem right when each method handles a completely different responsibility.
Is there a design pattern for this situation? Or any "clean" way to handle this?
This is exactly what facade pattern do.
Try to extract the three methods to another class, and make them private. Expose a single method MyMethod that calls the other methods in the desired order. Clients should use Facade.MyMethod
More details: https://en.m.wikipedia.org/wiki/Facade_pattern
I suppose you should leave control of execution for yourself and give possibility just to set what should be executed.
public interface IMethodsExecutor
{
void Execute();
void ShouldRunMethod1();
void ShouldRunMethod2();
void ShouldRunMethod3();
}
public class MethodsExecutor: IMethodsExecutor
{
private bool _runMethod1;
private bool _runMethod2;
private bool _runMethod3;
public MethodsExecutor()
{
_runMethod1 = false;
_runMethod2 = false;
_runMethod3 = false;
}
public void ShouldRunMethod1()
{
_runMethod1 = true;
}
public void ShouldRunMethod2()
{
_runMethod2 = true;
}
public void ShouldRunMethod3()
{
_runMethod3 = true;
}
private void Method1()
{
}
private void Method2()
{
}
private void Method3()
{
}
public void Execute()
{
if (_runMethod1)
{
Method1();
}
if (_runMethod2)
{
Method2();
}
if (_runMethod3)
{
Method3();
}
}
}
So that the usage will be:
IMethodsExecutor methodsExecutor = new MethodsExecutor();
methodsExecutor.ShouldRunMethod1();
methodsExecutor.ShouldRunMethod3();
methodsExecutor.Execute();

Force code to execute in order?

I am seeing a strange problem in my C# code. I have something like this:
public static class ErrorHandler {
public static int ErrorIgnoreCount = 0;
public static void IncrementIgnoreCount() {
ErrorIgnoreCount++;
}
public static void DecrementIgnoreCount() {
ErrorIgnoreCount--;
}
public static void DoHandleError() {
// actual error handling code here
}
public static void HandleError() {
if (ErrorIgnoreCount == 0) {
DoHandleError();
}
}
}
public class SomeClass {
public void DoSomething() {
ErrorHandler.IncrementIgnoreCount();
CodeThatIsSupposedToGenerateErrors(); // some method; not shown
ErrorHandler.DecrementIgnoreCount();
}
}
The problem is that the compiler often decides that the order of the three calls in the DoSomething() method is not important. For example, the decrement may happen before the increment. The result is that when the code that is supposed to generate errors is run, the error handling code fires, which I don't want.
How can I prevent that?
Add Trace or Logs to your code in IncrementIgnoreCount, DecrementIgnoreCount and HandleError function.
That will help you to view real call order.

Would it be simple to change this code for thread synchronized queueing?

I am trying to run the code from the article Thread Synchronized Queing
but getting compilation error:
The type or namespace name 'T' could not be found (are you missing a
using directive or an assembly reference?)
My guess is that it is using generics and the change should be pretty trivial though I have not much experience with it.
How should I change this code?
I hope for the pretty simple change, otherwise just forget about it
The code from that article:
using System;
using System.Collections;
using System.Collections.Generic;//per comment by #jam40jeff to answer
using System.Threading;
namespace QueueExample
{
public class SyncQueue// per answer --> public class SyncQueue<T>
{
private WaitHandle[] handles = {
new AutoResetEvent(false),
new ManualResetEvent(false),
};
private Queue _q = new Queue();
////per comment by #jam40jeff to answer, the above line should be changed to
// private Queue<T> _q = new Queue<T>();
public int Count
{
get
{
lock (_q)
{
return _q.Count;
}
}
}
public T Peek() //******error************************
{
lock (_q)
{
if (_q.Count > 0)
return _q.Peek();
}
return default(T);//******error************************
}
public void Enqueue(T element) //******error************************
{
lock (_q)
{
_q.Enqueue(element);
((AutoResetEvent)handles[0]).Set();
}
}
public T Dequeue(int timeout_milliseconds)//******error************************
{
T element;//******error************************
try
{
while (true)
{
if (WaitHandle.WaitAny(handles, timeout_milliseconds, true) == 0)
{
lock (_q)
{
if (_q.Count > 0)
{
element = _q.Dequeue();
if (_q.Count > 0)
((AutoResetEvent)handles[0]).Set();
return element;
}
}
}
else
{
return default(T);//******error************************
}
}
}
catch (Exception e)
{
return default(T);//******error************************
}
}
public T Dequeue() //******error************************
{
return Dequeue(-1);
}
public void Interrupt()
{
((ManualResetEvent)handles[1]).Set();
}
public void Uninterrupt()
{
// for completeness, lets the queue be used again
((ManualResetEvent)handles[1]).Reset();
}
}
}
Update:
After changing to
public class SyncQueue<T>
according to answer, it was also necessary to change from:
return _q.Peek();
to
return (T)_q.Peek();
and from
element = _q.Dequeue();
to
element = (T)_q.Dequeue();
Update2:
Per comment of #jam40jeff to the answer:
"Change _q to be of type Queue<T>. Then you will need the using statement, but you won't need the casts to T"
my updates above were bad
Maybe it's the mistake from author, class SyncQueue should be generic:
public class SyncQueue<T>
And to use generic, you also add one more using:
using System.Collections.Generic;
Then the code above should be fine.

Wrap asynchronous calls with synchronous method

I have a 3rd party DLL with an asynchronous method that I want to wrap with another method that waits for its result.
I started writing a class to hide the functionality, but now I can't work out how to wait for Doc.Completed to be called by the DLL after this.version.DownloadFile(this) in Doc.Download.
The DLL calls InitTransfer, then OnProgressNotify a number of times, then Completed. OnError may be called at any stage, but Completed is always called last. I don't care about InitTransfer, OnProgressNotify or OnError.
I have read
Asynchronous call in synchronous method and Turn asynchronous calls into synchronous but I don't understand how to apply the answers to this case.
I'm using C# 4.
public class Doc : SomeInterfaceFromTheDll
{
private readonly IVersion version; // An interface from the DLL.
private bool downloadSuccessful;
public Doc(IVersion version)
{
this.version = version;
}
public bool Download()
{
this.version.DownloadFile(this);
return ??? // I want to return this.downloadSuccessful after Completed() runs.
}
public void Completed(short reason)
{
Trace.WriteLine(string.Format("Notify.Completed({0})", reason));
this.downloadSuccessful = reason == 0 ? true : false;
}
public void InitTransfer(int totalSize)
{
Trace.WriteLine(string.Format("Notify.InitTransfer({0})", totalSize));
}
public void OnError(string errorText)
{
Trace.WriteLine(string.Format("Notify.OnError({0})", errorText));
}
public void OnProgressNotify(int bytesRead)
{
Trace.WriteLine(string.Format("Notify.OnProgressNotify({0})", bytesRead));
}
}
This can be achieved using a ManualResetEvent as shown below. There are a few caveats though. The primary one being that this mechanism does not permit you to call Download() on the same Doc instance on multiple threads at the same time. If you need to do this, then a different approach may be required.
public class Doc : SomeInterfaceFromTheDll
{
private readonly IVersion version; // An interface from the DLL.
private readonly ManualResetEvent _complete = new ManualResetEvent(false);
private bool downloadSuccessful;
// ...
public bool Download()
{
this.version.DownloadFile(this);
// Wait for the event to be signalled...
_complete.WaitOne();
return this.downloadSuccessful;
}
public void Completed(short reason)
{
Trace.WriteLine(string.Format("Notify.Completed({0})", reason));
this.downloadSuccessful = reason == 0;
// Signal that the download is complete
_complete.Set();
}
// ...
}

Categories

Resources