I have a classes for working with a web service (Windows Phone 8 app). My main question is about the thread-safety of the solutions. I think there will be problems with a static class GYApi
. After all, static classes aren't inherently thread safe. But not only in a static class.
If synchronization is necessary for locking, then how it will affect the performance?
GYResponseGeneric
is an open type for deserializing JSON to objects:
[DataContract]
public class GYResponseGeneric<T>
{
[DataMember(Name = "code")]
public int Code { get; set; }
[DataMember(Name = "message")]
public string Message { get; set; }
[DataMember(Name = "result")]
public T Result { get; set; }
}
Helpers class for passing some parameters:
public class RequestGeneric<T>
{
public HttpWebRequest HttpRequest { get; set; }
public string Url { get; set; }
public string PostData { get; set; }
public Action<GYResponseGeneric<T>, Exception> CallBack { get; set; }
}
PostRequester
is a singleton. This class sends post data to a web server (HttpWebRequest
), gets JSON from the web service and deserializes it. It invokes callback delegate .Invoke(response, error)
.
public sealed class PostRequester
{
static PostRequester instance = null;
static readonly object padlock = new object();
public static PostRequester Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new PostRequester();
}
return instance;
}
}
}
private PostRequester() { }
public void SendPost<T>(string postData, Action<GYResponseGeneric<T>, Exception> callback)
{
Task.Factory.StartNew(() => SendPostThread<T>(new RequestGeneric<T>
{
CallBack = callback,
PostData = postData,
}));
}
public void SendPostThread<T>(RequestGeneric<T> request)
{
...
webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback<T>), new RequestGeneric<T>()
{
HttpRequest = webRequest,
PostData = request.PostData,
Url = UrlRequest,
CallBack = request.CallBack,
});
...
}
private void GetRequestStreamCallback<T>(IAsyncResult asynchronousResult)
{
...
// Start the web request
request.HttpRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback<T>), request);
...
}
private void GetResponseCallback<T>(IAsyncResult asynchronousResult)
{
using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(gyResponse)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(GYResponseGeneric<T>));
GYResponseGeneric<T> responseObj = (GYResponseGeneric<T>)serializer.ReadObject(stream);
if (request.CallBack != null)
{
//get response Code (status response), Invoke callback etc
}
}
}
Static class for creating Post
data and passing it to PostRequester
:
public static partial class GYApi
{
...
public static void GetInfo(string uid, Action<GYResponseGeneric<GYUser>, Exception> callback)
{
string model = "User";
string method = "getInfo";
Params parametrs = new Params();
parametrs.Uid = uid;
string request = PostRequester.Instance.GetRequestString(model, method, parametrs);
PostRequester.Instance.SendPost<GYUser>(request, callback);
}
public static void SetLocation(GeoCoordinate location, Action<GYResponseGeneric<bool>, Exception> callback)
{
string model = "User";
string method = "setLocation";
Params parametrs = new Params();
parametrs.Latitude = (float)location.Latitude;
parametrs.Longitude = (float)location.Longitude;
string request = PostRequester.Instance.GetRequestString(model, method, parametrs);
PostRequester.Instance.SendPost<bool>(request, callback);
}
...
}
Example of calling API:
GYApi.GetInfo((response, error) =>
{
if (error != null)
{
...
return;
}
GYUser user = response.Result;
})