Duplex WCF net.tcp service disposed object exception for my client - c#

I implemented a client-server application for chatting with WCF. And i have a callback for broadcasting. It was working properly until i changed some functions. I was using my dataset fix data. It was initialized on my server and was used. I implemented an XML parser mechanism and then i'm getting an error like that:
Cannot access a disposed object. Object name:
'System.ServiceModel.InstanceContext'.
I'm using my service like that:
System.ServiceModel.InstanceContext context = new System.ServiceModel.InstanceContext(this.cb);
this._client = new WCFDevComServiceClient(context);
and then i'm openning this._client just one time and i'm using this object for my each call. (I don't close this object anytime.)
If i open before each call and then close it, then it's working. But in this case my callback function doesn't work. And i can't broadcast. So I can't close my client object.
Do you have any further information about this error? Or any fix suggestion?
My Service Codes:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class WCFDevComService : IWCFDevComService
{
private const string deviceXmlPath = #"D:\MyDocuments\Visual Studio 2015\Projects\WCFBroadcastorService\WCFDeviceCom\WCFDeviceCom_Service\bin\Devices.xml";
private const string userXmlPath = #"D:\MyDocuments\Visual Studio 2015\Projects\WCFBroadcastorService\WCFDeviceCom\WCFDeviceCom_Service\bin\Users.xml";
private DbOperations.DbOperations dbOperator = new DbOperations.DbOperations();
private static List<User> UserCollection = new List<User>();
private static Dictionary<string, IWCFDevComServiceBroadcastorCallback> clients = new Dictionary<string, IWCFDevComServiceBroadcastorCallback>();
private static object locker = new object();
private List<Device> deviceCollection = new List<Device>();
public bool LoginToServer(string clientName)
{
bool retVal = false;
if (clientName != "")
{
retVal = CheckUserName(clientName);
if (true == retVal)
{
try
{
IWCFDevComServiceBroadcastorCallback callback =
OperationContext.Current.GetCallbackChannel<IWCFDevComServiceBroadcastorCallback>();
if (clients.Keys.Contains(clientName))
clients.Remove(clientName);
clients.Add(clientName, callback);
}
catch (Exception ex)
{
throw;
}
}
}
return retVal;
}
private bool CheckUserName(string clientName)
{
lock (locker)
{
UserCollection = dbOperator.QueryForGetAllUsers(userXmlPath);
foreach (var user in UserCollection)
{
if (user.m_userName.Contains(clientName))
{
return true;
}
}
return false;
}
}
public List<Device> GetAllDevicesInformation()
{
try
{
return GetInformationFromDeviceXML();
}
catch (Exception ex)
{
throw;
return null;
}
}
private List<Device> GetInformationFromDeviceXML()
{
try
{
lock (locker)
{
deviceCollection = dbOperator.QueryForGetAllDevices(deviceXmlPath);
}
return deviceCollection;
}
catch (Exception ex)
{
throw;
return null;
}
}
public int GetNumberOfDevices()
{
try
{
lock (locker)
{
//todo: GetNumberOfDevicesFromXML
return dbOperator.QueryForGetDeviceCount(deviceXmlPath);
}
}
catch (Exception ex)
{
throw;
return 0;
}
}
public Device GetDeviceInformation(int index)
{
List<Device> deviceCollection = GetInformationFromDeviceXML();
return deviceCollection[index];
}
public int BlockedDevice(int index, User user)
{
try
{
if (index < 0 && user == null)
return -1; //fail
lock (locker)
{
if (deviceCollection[index].m_state.m_state != States.Free)
return 1; // isn't free for blocking
DeviceState tmpState = new DeviceState();
tmpState.m_state = States.Locked;
tmpState.m_lockedUser = user;
deviceCollection[index].m_state = tmpState;
//todo: UpdateXML
dbOperator.QueryForUpdateDeviceStateById(deviceXmlPath, index + 1, tmpState);
//deviceCollection = GetInformationFromDeviceXML();
NotifyOtherClients(index, user);
return 0; //success
}
}
catch (Exception ex)
{
throw;
return -1;
}
}
public int FreeDevice(int index, User user)
{
try
{
if (index < 0 && user == null)
return -1; //fail
lock (locker)
{
if (deviceCollection[index].m_state.m_state != States.Locked)
return 1; // isn't locked to free
if (deviceCollection[index].m_state.m_lockedUser.m_userName != user.m_userName && user.m_userPermission != Permission.ADMIN)
return 2; // isn't right person
DeviceState tmpState = new DeviceState();
tmpState.m_state = States.Free;
tmpState.m_lockedUser = null;
deviceCollection[index].m_state = tmpState;
//todo: UpdateXML
dbOperator.QueryForUpdateDeviceStateById(deviceXmlPath, index + 1, tmpState);
//deviceCollection = GetInformationFromDeviceXML();
NotifyOtherClients(index, user);
return 0; //success
}
}
catch (Exception ex)
{
throw;
return -1;
}
}
public Permission GetPermission(string userName)
{
lock (locker)
{
foreach (var user in UserCollection)
{
if (user.m_userName == userName)
return user.m_userPermission;
}
return Permission.USER;
}
}
private void NotifyOtherClients(int index, User user)
{
try
{
var inactiveClients = new List<string>();
EventDataType eventData = new EventDataType();
eventData.ClientName = user.m_userName;
eventData.Index = index;
foreach (var client in clients)
{
if (client.Key != eventData.ClientName)
{
try
{
client.Value.BroadcastToClient(eventData);
}
catch (Exception ex)
{
inactiveClients.Add(client.Key);
}
}
}
if (inactiveClients.Count > 0)
{
foreach (var client in inactiveClients)
{
clients.Remove(client);
}
}
}
catch (Exception ex)
{
throw;
}
}
}

Related

Is there a way to pass a method into another method in c# and what's the best way to do it?

I'm trying to keep my code dry. I have 5 methods that have the same bulk of code but I don't want the write them all multiple times. Below are 2 sample methods. I want to know how I can consolidate it into 1 generic method. Is that the best way to do it?
public async Task<PlaylistListResponse> GetPlaylistsFromChannel(string channelID, bool forceRefresh = false)
{
string barrelURL = "GetPlaylistsFromChannel" + channelID.Trim();
PlaylistListResponse results = default;
if(forceRefresh != true)
{
results = GetCached<PlaylistListResponse>(barrelURL);
}
else
{
try
{
if (object.Equals(results, default(PlaylistListResponse)))
{
var playlistFromChannelRequest = youtubeService.Playlists.List("id");
playlistFromChannelRequest.ChannelId = channelID;
playlistFromChannelRequest.MaxResults = 50;
results = await playlistFromChannelRequest.ExecuteAsync();
Barrel.Current.Add(barrelURL, results, TimeSpan.FromDays(30));
}
return results;
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
}
return results;
}
public async Task<PlaylistListResponse> GetPlaylistsFromChannel(string channelID, bool forceRefresh = false)
{
string barrelURL = "GetPlaylistsFromChannel" + channelID.Trim();
PlaylistListResponse results = default;
if (forceRefresh != true)
{
results = GetCached<PlaylistListResponse>(barrelURL);
}
else
{
try
{
if (object.Equals(results, default(PlaylistListResponse)))
{
var videosFromPlaylistRequest = youtubeService.PlaylistItems.List("snippet");
videosFromPlaylistRequest.PlaylistId = playlistID;
videosFromPlaylistRequest.MaxResults = 50;
results = await videosFromPlaylistRequest.ExecuteAsync();
Barrel.Current.Add(barrelURL, results, TimeSpan.FromDays(30));
}
return results;
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
}
return results;
}
I've tried creating a generic method but can't find a way to make changes to it as I don't want a multitude of if statements.
public async Task<T> GetAsync<T>(string barrelURL, int days = 7, bool forceRefresh = false)
{
results = default(T);
if (!CrossConnectivity.Current.IsConnected)
results = Barrel.Current.Get<T>(barrelURL);
if (!forceRefresh && !Barrel.Current.IsExpired(barrelURL))
results = Barrel.Current.Get<T>(barrelURL);
try
{
if (object.Equals(results, default(T)))
{
//myMethodsCode??
Barrel.Current.Add(barrelURL, results, TimeSpan.FromDays(days));
}
return results;
}
catch (Exception ex)
{
Console.WriteLine($"Unable to get information from server {ex}");
}
}
A possible solution to this problem would be to create a generic method and pass delegates that represent differing parts into it.
public async Task<T> GetFromChannel<T>(
string channelID,
Func<Task<T>> resultGetter,
bool forceRefresh = false)
{
string barrelURL = "GetPlaylistsFromChannel" + channelID.Trim();
T results = default;
if (forceRefresh != true)
{
results = GetCached<T>(barrelURL);
}
else
{
try
{
if (object.Equals(results, default(T)))
{
results = await resultGetter();
Barrel.Current.Add(barrelURL, results, TimeSpan.FromDays(30));
}
return results;
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
}
return results;
}
And then you can insert the differing parts using other methods or lambda exressions, for example:
public Task<PlaylistListResponse> GetPlaylistsFromChannel(
string channelID,
bool forceRefresh = false)
{
return GetFromChannel<PlaylistListResponse>(
channelID,
async () =>
{
var videosFromPlaylistRequest = youtubeService.PlaylistItems.List("snippet");
videosFromPlaylistRequest.PlaylistId = playlistID;
videosFromPlaylistRequest.MaxResults = 50;
return await videosFromPlaylistRequest.ExecuteAsync();
},
forceRefresh);
}

Removing element from SortedSet in C#

I'm trying to remove an element from a Redis Sorted list without success
public bool Delete(int id)
{
try
{
var redisManager = new RedisManagerPool(Global.RedisConnector);
using (var redis = redisManager.GetClient())
{
var entities = redis.As<BookingRequestModel>();
var list = entities.SortedSets["BookingRequests"].GetAll();
//count = 320
var model = list.First(z=>z.Id == id);
list.Remove(model);
//count 319 - however when I refresh the page I still see my old data in grid ...
entities.Save();
return true;
}
}
catch (Exception ex)
{
return false;
}
}
also tried like this :
public bool Delete(int id)
{
try
{
var redisManager = new RedisManagerPool(Global.RedisConnector);
using (var redis = redisManager.GetClient())
{
var entities = redis.As<BookingRequestModel>();
var list = entities.SortedSets["BookingRequests"];
var model = list.First(z=>z.Id == id);
var result = entities.RemoveItemFromSortedSet(list, model); // result is false
entities.Save();
return true;
}
}
catch (Exception ex)
{
return false;
}
}
As I commented there I still can see the old data after removing them from grid.
Can you please help me with this ?
Don't understand why , but this is working :
public bool Delete(int id)
{
try
{
var redisManager = new RedisManagerPool(Global.RedisConnector);
using (var redis = redisManager.GetClient())
{
var items = redis.GetAllItemsFromSortedSet("BookingRequests");
foreach (var item in items)
{
var dto = item.FromJson<BookingRequestModel>();
if (dto.Id == id)
{
redis.RemoveItemFromSortedSet("BookingRequests", item);
break;
}
}
return true;
}
}
catch (Exception ex)
{
return false;
}
}

FireClient does not work and return to class with any error in Xamarin?

this is login function but when compiler compile the line where "value" mean its return to Xamarin form without proceeding further
Thank You
async public Task<User> GetLogin(User info)
{
User login = new User();
var firebase = new FirebaseClient("https://xyz.firebaseio.com/");
try
{
var value = await firebase.Child("User").OrderByValue().OnceAsync<User>();
foreach (var item in value)
{
if (info.Username == item.Object.Username && info.Password == item.Object.Password )
{
login.Id = item.Object.Id;
login.Fullname = item.Object.Fullname;
login.Username = item.Object.Username;
login.Password = item.Object.Password;
login.Role = item.Object.Role;
MasterPage session = new MasterPage(login);
return login;
}
else { }
}
}
catch (Exception ex) { }
return null;
}

Calling an async method inside Background worker dosen't report progress paralelly

I am calling an async method that returns a Task < CurrentCartridgeStatus> from Background worker. Thing is until the CurrentCartridgeStatus changes its state I want to keep calling it. But I am not awaiting on this method call because making the DoWork method async is giving me an exception.
But in my case with my current call(Please see the StartCurrentRun method) the background worker initially reports 1% then it seems to be staying idle, and after the status changes then it reports the rest 99%. Please help how can I make the Background worker report progress in parallel with StartCurrentRun method.
private void StartCurrentRun(bool obj)
{
this.worker = new BackgroundWorker();
this.worker.WorkerReportsProgress = true;
this.worker.WorkerSupportsCancellation = true;
this.worker.DoWork += this.DoWork;
this.worker.ProgressChanged += this.ProgressChanged;
this.worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
IsLiveProgress = true;
StartTimer();
this.worker.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
CreateEventLogs.WriteToEventLog(string.Format("Run with Assay:{0} Volume{1} has been started", SelectedAssay, SelectedVolume));
if (worker.CancellationPending == true)
{
e.Cancel = true;
return;
}
int current = 1;
CurrentCartridgeStatus status = CurrentCartridgeStatus.NotProcessed;
var instance = ConnectToInstrument.InstrumentConnectionInstance;
do
{
var result = instance.StartCurrentRun(SelectedAssay.display_name, int.Parse(SelectedVolume.Remove(SelectedVolume.Length - 2, 2)));
//var result = Test(current);
status = result.Result;
CurrentStatus = status.ToString();
CreateEventLogs.WriteToEventLog("Run status - " + CurrentStatus);
//Thread.Sleep(2000);
worker.ReportProgress(Math.Min(current, 100));
current++;
}
while (status != CurrentCartridgeStatus.Processed);
ConnectToInstrument.IsAlreadyExecuted = false;
if (current < 100)
{
worker.ReportProgress(current + (100 - current));
}
}
Here is the StartCurrentRun method. It internally calls some firmware logic. Just to make this more clear here is the entire ConnectToInstrument Class.
public class ConnectToInstrument
{
private EventProxy _updater;
private IInstrument _instrument;
private QpCallBack _cb;
//private IQEvent #event;
private QpWrapper _qp;
private InstrumentTypes _type;
private CurrentInstrumentStatus InstrumentCurrentStatus = CurrentInstrumentStatus.NotReady;
private static ManualResetEvent manualResetEvent = new ManualResetEvent(false);
public static bool IsAlreadyExecuted = false;
public bool IsConnected { get; set; }
private static ConnectToInstrument _instrumentConnectionInstance;
public static ConnectToInstrument InstrumentConnectionInstance
{
get
{
if (_instrumentConnectionInstance == null)
{
_instrumentConnectionInstance = new ConnectToInstrument();
}
return _instrumentConnectionInstance;
}
}
private ConnectToInstrument()
{
try
{
_cb = new QpCallBack();
_qp = new QpWrapper();
//var config = new ConfigManager();
//var client = new Dna2Client();
_type = InstrumentTypes.Simulator;
var factory = new ApiFactory(_cb, _qp, _type);
_instrument = factory.GetInstrument();
InitializeQf();
_updater = new EventProxy();
_updater.Start(1);
StartUiProxy().Forget();
}
catch (Exception ex)
{
//Log to Error Log
}
}
private async Task<object> StartUiProxy()
{
while (true)
{
try
{
var #event = await _updater.GetEvent();
switch ((QpSignals)#event.QSignal)
{
case QpSignals.INSTRUMENT_STATUS:
{
var status = #event as UiEvent<InstrumentStatus>;
if (status.Value != InstrumentStatus.Ready)
{
InstrumentCurrentStatus = CurrentInstrumentStatus.NotConnected;
continue;
}
else
{
InstrumentCurrentStatus = CurrentInstrumentStatus.Ready;
return Task.FromResult<object>(InstrumentStatus.Ready);
}
}
case QpSignals.TRAY_STATUS:
{
var status = #event as UiEvent<TrayStatus>;
if (status.QSignal == 6 && status.Value == TrayStatus.Opened)
{
return Task.FromResult<object>(TraySignals.OPEN);
}
else if (status.QSignal == 6 && status.Value == TrayStatus.Opened)
{
return Task.FromResult<object>(TraySignals.CLOSE);
}
return null;
}
case QpSignals.PROCESS_CARTRIDGE:
{
var status = #event as UiEvent<CartridgeStatus>;
if (status.Value == CartridgeStatus.Processing)
{
return status;
}
else if (status.Value == CartridgeStatus.Processed)
{
return status;
}
return null;
}
}
}
catch (Exception ex)
{
//Log to Error Log
}
}
}
private void InitializeQf()
{
QF.Instance.Initialize((int)QpSignals.MAX_SIGNAL - 1);
}
public async Task<bool> Connect()
{
bool status = false;
string[] ports = new string[40];
if (_type == InstrumentTypes.Dgx)
{
ports = await ComPortInfo.GetAvailablePortNamesForDevice("USB Serial Port");
if (ports == null || ports.Length == 0)
{
Exception ex = new Exception("No Serial Devices found.");
//Log
return false;
}
}
try
{
string thermPort = _type == InstrumentTypes.Simulator ? string.Empty : ports[0]; //ports[0] should be changed to combobox selected value
status = _instrument.Connect(ports[0]);
}
catch (Exception ex)
{
Debug.Write(ex.Message);
}
return status;
}
public async Task<CurrentInstrumentStatus> GetCurrentInstrumentStatus()
{
return await Task.FromResult(InstrumentCurrentStatus);
//_cb.InstrumentStatusUpdates(InstrumentStatus.Ready);
//var value = await _updater.GetEvent();
//var status = value as UiEvent<InstrumentStatus>;
//if (status.QSignal == 5 && status.Value == InstrumentStatus.Ready)
//{
// return CurrentInstrumentStatus.Ready;
//}
//return CurrentInstrumentStatus.Error;
}
public async Task<CurrentCartridgeStatus> StartCurrentRun(string Assay, int volume)
{
object value;
UiEvent<CartridgeStatus> status;
do
{
//await Task.Delay(1000);
//_cb.ProcessCartridge(CartridgeStatus.Processing);
if (!IsAlreadyExecuted)
{
_instrument.ProcessCartridge();
}
IsAlreadyExecuted = true;
//value = await StartUiProxy();
value = await _updater.GetEvent();
status = value as UiEvent<CartridgeStatus>;
}
while (status == null);
try
{
//IQEvent value;
if (status.QSignal == 9 && status.Value == CartridgeStatus.Processing)
{
return CurrentCartridgeStatus.Processing;
}
if (status.QSignal == 9 && status.Value == CartridgeStatus.Processed)
{
return CurrentCartridgeStatus.Processed;
}
}
catch (Exception ex)
{
//Log it
}
return CurrentCartridgeStatus.Unidentified;
}
}
Here is the CurrentCartridgeStatus enum
public enum CurrentCartridgeStatus
{
Unidentified = 0,
NotProcessed = 1,
Processing = 2,
Processed = 3
}

Edit field in all documents in Azure DocumentDb

I have my data in DocumentDb.
I want to edit one field in all documents with Type == 8.
How I can do it?
Create console app for it
Use Azure Functions
I tried the second option and it not working.
public static void Run(string myQueueItem, dynamic inputDocument)
{
if(inputDocument.Type == 8) {
inputDocument.Entity.Discount.Name = inputDocument.Entity.Discount.Name + "smth";
}
}
Do you have any idea?
Below code seems naïve and RU-wasteful but will work.
DocumentClient _documentDbclient;
// Database configuration
static readonly string DocumentDbKeyConfig = "3dzS7T3a8lgEblkEnzSsdfasdfasf2omI1cp7==";
static readonly string DocumentDbEndPointConfig = "https://your-docdb.documents.azure.com:443/";
static readonly string DocumentDbDatabaseNameConfig = "your-database-name";
void Main()
{
string collectionName = "TestCollection";
Uri uri = UriFactory.CreateDocumentCollectionUri(DocumentDbDatabaseNameConfig, collectionName);
InitializeDocumentDbAsync(DocumentDbDatabaseNameConfig).ConfigureAwait(false);
createDocumentCollectionIfNotExistAsync(DocumentDbDatabaseNameConfig, collectionName).ConfigureAwait(false);
DocumentCollection collection = _documentDbclient.ReadDocumentCollectionAsync(uri).Result;
var query = _documentDbclient.CreateDocumentQuery(uri);
var queryList = query.ToList();
int index = 0;
int count = 50; // number of item to fetch at a time
while (true)
{
var result = queryList.Skip(index * count).Take(count);
if (!result.Any())
{
// end iterating.
return;
}
foreach (Document element in result)
{
JObject j = (dynamic)element;
if(j["Type"] != 8) continue;
j["YourProperty"] = "Some Value"; // edit value.
var upsertedResult = _documentDbclient.UpsertDocumentAsync(uri, j, null, true).Result;
}
++index;
}
}
public async Task InitializeDocumentDbAsync(string databaseName)
{
// Create a new instance of the DocumentClient
_documentDbclient = new DocumentClient(
new Uri(DocumentDbEndPointConfig), DocumentDbKeyConfig);
// Check if the database FamilyDB does not exist
try
{
await _documentDbclient.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(databaseName));
}
catch (DocumentClientException de)
{
// If the database does not exist, create a new database
if (de.StatusCode == HttpStatusCode.NotFound)
{
await _documentDbclient.CreateDatabaseAsync(new Database { Id = databaseName });
}
else
{
throw;
}
}
catch (Exception e)
{
throw;
}
}
private async Task createDocumentCollectionIfNotExistAsync(string databaseName, string collectionName)
{
try
{
await
_documentDbclient.ReadDocumentCollectionAsync(UriFactory.CreateDocumentCollectionUri(databaseName, collectionName));
}
catch (DocumentClientException de)
{
// not exist
throw;
}
catch (Exception e)
{
// do nothing.
}
}

Categories