I am using System.Net.Http.HttpClient to make postaysnc request. While request is in progress I unplug the network cable, receive HttpRequestException.
After some time plug the network cable again and make the postasync request, getting the HttpRequestException - sometimes i get the response server not available,sometimes timeout
Do i need to dispose the httpclient on exception and recreate when the request is made? How to make the query successful on network restore.
private async Task<string> GetServerResult()
{
try
{
var response = await myHttpClient.PostAsync("https://google.com", httpContent);
response.EnsureSuccessStatusCode();
}
catch (HttpRequestException ex)
{
throw new HttpRequestException(ex.Message, ex.InnerException);
}
}
As per your requirement, you have to change implement some sort of implementation in that case. My proposed solution is use to a caching mechanism at WCF Client and update it periodically.
The very simple implementation could be as: You have a very simple singleton class of and a periodic Timer fetches the data from your mentioned endpoint. It stores the last cached data so that you have a copy of the data and when the hits are failed you can configure a fallback mechanism for that. For instance you have an implementation like
//You single Cache class
public sealed class ClientCache
{
#region Singleton implementation
private static ClientCache _clientCache = new ClientCache();
private ClientCache()
{
}
public static ClientCache Instance => _clientCache;
#endregion
//Timer for syncing the data from Server
private Timer _timer;
//This data is the cached one
public string data = string.Empty;
internal void StartProcess()
{
//Initializing the timer
_timer = new Timer(TimeSpan.FromMinutes(1).TotalMilliseconds); //This timespan is configurable
//Assigning it an elapsed time event
_timer.Elapsed += async (e, args) => await SyncServerData(e, args);
//Starting the timer
_timer.Start();
}
//In this method you will request your server and fetch the latest copy of the data
//In case of failure you can maintain the history of the last disconnected server
private async Task ProcessingMethod(object sender, ElapsedEventArgs e)
{
//First we will stop the timer so that any other hit don't come in the mean while
timer.Stop();
//Call your api here
//Once the hit is completed or failed
//On Success you will be updating the Data object
//data = result from your api call
//Finally start the time again as
timer.Start();
}
}
Now coming to Step two where to initialize the ClientCache Class. The best options are to initialize it in Global.asax class
protected void Application_Start()
{
//As
ClientCache.Instance.StartProcess();
}
Now whenever your frontend calls the method you don't need to go back to the server. Just send back the result from your cache as:
private Task<string> GetServerResult()
{
return Task.FromResult(ClientCache.Instance.data);
}
Related
I have started a timer when my hub connection is established in PushNotificationData method by clients requests.
As per timer interval, it does fetch the records from the db and push to the clients.
but when clients got disconnected ,this timer has to be stopped instead of pulling continuously.
So I have used OnDisconnected event to stop the timer. but unfortunately timer not getting stopped
here is my code:
public class NotifyHub : Hub
{
private string ConnectionId;
private int UserId;
private int UserTypeId;
Timer timer = new Timer();
public override Task OnConnected()
{
ConnectionId = Context.ConnectionId;
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
timer.Stop();
timer.Enabled = false;
//logic code removed for brevity
return base.OnDisconnected(stopCalled);
}
public void PushNotificationData(Int32 userId, Int16 userTypeId)
{
UserId = userId;
UserTypeId = userTypeId;
ConnectionId = Context.ConnectionId;
timer.Elapsed += Timer_Elapsed1;
timer.Interval = 6000;
timer.Enabled = true;
timer.Start();
}
private void Timer_Elapsed1(object sender, ElapsedEventArgs e)
{
var notificationParams = new PushNotificationRequest
{
FilterProperty = new Common.Filters.FilterProperty { Offset = 0, RecordLimit = 0, OrderBy = "datechecked desc" },
Filters = new List<Common.Filters.FilterObject> { new Common.Filters.FilterObject { LogicOperator = 0, ConditionOperator = 0, Function = 0, FieldName = "", FieldValue = "", FieldType = 0 } }
};
using (INotificationManager iNotifity = new NotificationManager())
{
var taskTimer = Task.Run(async () =>
{
var NotificationResult = iNotifity.GetPushNotificationData(notificationParams, UserId, UserTypeId);
//Sending the response data to all the clients based on ConnectionId through the client method NotificationToClient()
Clients.Client(ConnectionId).NotificationToClient(NotificationResult);
//Delaying by 6 seconds.
await Task.Delay(1000);
//}
});
}
}
}
When I debug it, it shows timer enabled=true even after OnDisconnected fires.
the moment OnDisconneted is executing , i can able to see that timer get updated enabled=false. after it come out from the OnDisconnected timer.enabledgot true again.
Read about the Hub Object Lifetime here. The important part is this
Because instances of the Hub class are transient, you can't use them to maintain state from one method call to the next. Each time the server receives a method call from a client, a new instance of your Hub class processes the message. To maintain state through multiple connections and method calls, use some other method such as a database, or a static variable on the Hub class, or a different class that does not derive from Hub. If you persist data in memory, using a method such as a static variable on the Hub class, the data will be lost when the app domain recycles.
You essentially creating a new timer every time a new Hub is created. So you land up with multiple timers all calling the Timer_Elapsed1 method. You could try making Timer static and keep track of the connection count. That way you could stop the timer when all clients are disconnected. Be aware though that even static variables are vulnerable to be lost if the app domain recycles (as pointed out in the docs above).
I'm trying to maintain a list of WebSockets for a server which only needs to send messages to the client and not receive any replies. When the WebSocket is created initially all I want to do is just add the socket reference to a list for later use.
...
static Dictionary<int,WebSocket> wsDict = new Dictionary<int,WebSocket>();
...
private Task ProcessWS(AspNetWebSocketContext context)
{
wsDict[id] = (context.WebSocket);
...
}
(Finishes running the method and returns)
The issue I'm having is that I believe GC is disposing of the WebSocket, so when I try to use it at a later time I receive 'System.ObjectDisposedException'. Is there any way of permanently stopping GC from disposing of the socket?
Edit:
Sorry for not being clear originally, the whole class which inherits ApiController is (as the name suggests) is a control. A client initiates the WebSocket via a GET request and it calls the method above where it tries to store the socket into a dictionary (mapped to a int). The dictionary itself is Static.
It saves it into the Dict fine and in the debugger everything looks great. Its just literally disposing it after ProccessWS is complete and I can't seem to find a way to stop it. If I add a loop/sleep timer to the bottom of the ProcessWS it works fine - but thats not a viable solution.
The is a problem which originally I wasn't sure if it would be possible as each of the REST calls are stateless yet I need to maintain and overall list of all the connections which seems to contradict the original statement.
You have to await reads while the WS is still connected:
public class WSHandler : IHttpHandler
{
public bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context)
{
if (context.IsWebSocketRequest)
{
context.AcceptWebSocketRequest(ProcessWS);
}
}
private async Task ProcessWS(AspNetWebSocketContext context)
{
WebSocket socket = context.WebSocket;
...
while (socket.State == WebSocketState.Open)
{
WebSocketReceiveResult result = await socket.ReceiveAsync(buffer, CancellationToken.None)
.ConfigureAwait(false);
...
}
}
}
I am working on a window services application and my window service will call one of the web services in certain intervals (for example 3 min). From the web service I will get data from a database and using that data I will send an email.
If I am having huge sets of rows in my db table it will take some time to send the mail. Here I have the problem: The window services send the first request and it will handle some set of records. So, while processing it by the web service, the window service sends another request to the web service before it has completed the first request.
Due to this, the web service gets the same records from db again and again whenever it receives a new request from the windows service.
Can any one suggest me how to lock the previous request until it completes its work or some other way to handle this situation?
Web Service call:
protected override void OnStart(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 180000;
timer.AutoReset = false;
timer.Enabled = true;
}
Inside Method
using (MailWebService call = new MailWebService())
{
try
{
call.ServiceUrl = GetWebServiceUrl();
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
call.CheckMailQueue();
}
catch (Exception ex)
{
LogHelper.LogWriter(ex);
}
finally
{
}
}
The Monitor class works great for this scenario. Here is an example of how to use it:
// This is the object that we lock to control access
private static object _intervalSync = new object();
private void OnElapsedTime(object sender, ElapsedEventArgs e)
{
if (System.Threading.Monitor.TryEnter(_intervalSync))
{
try
{
// Your code here
}
finally
{
// Make sure Exit is always called
System.Threading.Monitor.Exit(_intervalSync);
}
}
else
{
//Previous interval is still in progress.
}
}
There is also an overload for TryEnter that allows you to specify timeout for entering the section.
I have an API in which i do a lot of processing like sending a service bus queue message and receiving it, adding entries to table and then finally send an event to socket.io server. I want all this to be protected by concurrent executions. I am using Lock, but it doesnt seem to do the trick. Am i missing anything? below is my code
public class BroadcastController : ApiController
{
private readonly Object _Lock = new Object();
[HttpPost]
[ActionName("UploadRecording")]
public async Task<HttpResponseMessage> UploadRecording()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string path = Path.GetTempPath();
var provider = new MultipartFormDataStreamProvider(path);
// Read the form data and return an async task.
var response = await Request.Content.ReadAsMultipartAsync(provider);
// processing the mime content
lock (_Lock)
{
// sending and receiving service bus messages
// adding records to table
// sending an event to socket.io
return Request.CreateResponse(HttpStatusCode.OK, new ResponseMessage<PersistedAudioRecord> { SuccessCode = 1, Message = "Broadcast Uploaded", Data = updatedRecord });
} } }
Make the _Lock object static. Otherwise, you are using a different lock for each instance of the controller. Since the framework creates a new instance of the controller to process each request, each request is locking on a different _Lock object, thus providing no concurrency safety.
However, note that even a static lock object will only work if you have a single server. If you have multiple servers handling requests you'll need to manage concurrency by another means.
I'm using asynchronous calls for communication to my server. I written some component to collect all unauthorized requests and to resend them after user logs in. I written some test to produce 10 threads that are sending some requests without first being authorized. Than I wait for 20 seconds and do authorization and after that I wait for request to successfully finish. But problem appeared at EndGetResponse method which I call in my callback method. I done that this way:
public void InternalCallback(IAsyncResult result)
{
try
{
RequestState state = (RequestState)result.AsyncState;
IHttpWebRequest request = state.Request;
using (IHttpWebResponse response = responseGetter.GetResponse(request, result))
{
// ...
}
}
// ...
}
So, I made some custom class RequestState which has some higher level callbacks I need and it has request which I'll use to call EndGetResponse method. But this way I got error:
IAsyncResult object was not returned from the corresponding asynchronous method.
I changed this so I now have Request field in my callback class which I set before calling BeginGetResponse and I use that Request field when calling EndGetResponse in my callback.
public void InternalCallback(IAsyncResult result)
{
try
{
using (IHttpWebResponse response = responseGetter.GetResponse(this.Request, result))
{
// ...
}
}
// ...
}
Is this new solution valid one? Can you suggest is this good way to do this or how should I do this?