I have encountered a problem with pusherClient.wp8 package I installed from Nuget. Every time the app is sent to the background, I disconnect from pusher and unsubscribe from the channel. when I resume the app, the code hang when connection is re-established with pusher.
I have tried to reset the pusher object, reset the channel, create a new instance of pusher, and still nothing works, it seems there is a problem with the package, or rather the websocket disconnect method is failing to disconnect from pusher, however, when I close the app, everything get reseted. but this does not help me in instances when a user open a photopicker from my app.
Does anyone has a suggestion or know of another pusherclient I can use for windows phone 8. I have been struggling with this problem for weeks now.
Here is the github link of the package I used: https://github.com/bszypelow/PusherClient.WP8/blob/master/PusherClient.WP8
Thank you
public ConnectionState Connect()
{
var task = Task.Run(async () => await pusher.ConnectAsync()); ;
try
{
task.Wait();
}
catch (Exception ex)
{
Debug.WriteLine("Exception " + ex.Message + " at " + ex.Source + "Inner exception " + ex.InnerException + " additional data " + ex.Data);
}
return task.Result;
}
From looking at the source code I have a guess:
All the async methods never use .ConfigureAwait(false) which could be a reason for the dead lock.
Especially if you call it from the UI thread using the .Wait() or .Result. From event for example.
I suggest you to update the code (it's MIT license, you can do that):
public Task<Channel> Subscribe(string channelName)
{
if (_connection.State != ConnectionState.Connected)
throw new PusherException("You must wait for Pusher to connect before you can subscribe to a channel", ErrorCodes.NotConnected);
if (Channels.ContainsKey(channelName))
{
return Task.FromResult(Channels[channelName]);
}
// If private or presence channel, check that auth endpoint has been set
var chanType = ChannelTypes.Public;
if (channelName.ToLower().StartsWith("private-"))
chanType = ChannelTypes.Private;
else if (channelName.ToLower().StartsWith("presence-"))
chanType = ChannelTypes.Presence;
return SubscribeToChannel(chanType, channelName); //await is not needed here
}
private async Task<Channel> SubscribeToChannel(ChannelTypes type, string channelName)
{
switch (type)
{
case ChannelTypes.Public:
Channels.Add(channelName, new Channel(channelName, this));
break;
case ChannelTypes.Private:
AuthEndpointCheck();
Channels.Add(channelName, new PrivateChannel(channelName, this));
break;
case ChannelTypes.Presence:
AuthEndpointCheck();
Channels.Add(channelName, new PresenceChannel(channelName, this));
break;
}
if (type == ChannelTypes.Presence || type == ChannelTypes.Private)
{
string jsonAuth = await _options.Authorizer.Authorize(channelName, _connection.SocketID)
.ConfigureAwait(false); //do not capture the context!!
var template = new { auth = String.Empty, channel_data = String.Empty };
var message = JsonConvert.DeserializeAnonymousType(jsonAuth, template);
_connection.Send(JsonConvert.SerializeObject(new { #event = Constants.CHANNEL_SUBSCRIBE, data = new { channel = channelName, auth = message.auth, channel_data = message.channel_data } }));
}
else
{
// No need for auth details. Just send subscribe event
_connection.Send(JsonConvert.SerializeObject(new { #event = Constants.CHANNEL_SUBSCRIBE, data = new { channel = channelName } }));
}
return Channels[channelName];
}
You can checkout the source code, than if you don't use it now you can install trial version of ReSharper and this plug-in. They will help you to find all the lines where .ConfigureAwait is missing.
Related
I'm trying to create a Class to manage my Cloud Firestore requests (like any SQLiteHelper Class). However, firebase uses async calls and I'm not able to return a value to other scripts.
Here an example (bool return):
public bool CheckIfIsFullyRegistered(string idUtente)
{
DocumentReference docRef = db.Collection("Utenti").Document(idUtente);
docRef.GetSnapshotAsync().ContinueWithOnMainThread(task =>
{
DocumentSnapshot snapshot = task.Result;
if (snapshot.Exists)
{
Debug.Log(String.Format("Document {0} exist!", snapshot.Id));
return true; //Error here
}
else
{
Debug.Log(String.Format("Document {0} does not exist!", snapshot.Id));
}
});
}
Unfortunately, since Firestore is acting as a frontend for some slow running I/O (disk access or a web request), any interactions you have with it will need to be asynchronous. You'll also want to avoid blocking your game loop if at all possible while performing this access. That is to say, there won't be a synchronous call to GetSnapshotAsync.
Now there are two options you have for writing code that feels synchronous (if you're like me, it's easier to think like this than with callbacks or reactive structures).
First is that GetSnapshotAsync returns a task. You can opt to await on that task in an async function:
public async bool CheckIfIsFullyRegistered(string idUtente)
{
DocumentReference docRef = db.Collection("Utenti").Document(idUtente);
// this is equivalent to `task.Result` in the continuation code
DocumentSnapshot snapshot = await docRef.GetSnapshotAsync()
return snapshot.Exists;
}
The catch with this is that async/await makes some assumptions about C# object lifecycle that aren't guaranteed in the Unity context (more information in my related blog post and video). If you're a long-time Unity developer, or just want to avoid this == null ever being true, you may opt to wrap your async call in a WaitUntil block:
private IEnumerator CheckIfIsFullyRegisteredInCoroutine() {
string idUtente;
// set idUtente somewhere here
var isFullyRegisteredTask = CheckIfIsFullyRegistered(idUtente);
yield return new WaitUntil(()=>isFullyRegisteredTask.IsComplete);
if (isFullyRegisteredTask.Exception != null) {
// do something with the exception here
yield break;
}
bool isFullyRegistered = isFullyRegisteredTask.Result;
}
One other pattern I like to employ is to use listeners instead of just retrieving a snapshot. I would populate some Unity-side class with whatever the latest data is from Firestore (or RTDB) and have all my Unity objects ping that MonoBehaviour. This fits especially well with Unity's new ECS architecture or any time you're querying your data on a per-frame basis.
I hope that all helps!
This is how i got it to work, but excuse my ignorance as i've only been using FBDB for like a week.
Here is a snippet, I hope it helps someone.
Create a thread task extension to our login event
static Task DI = new System.Threading.Tasks.Task(LoginAnon);
Logging in anon
DI = FirebaseAuth.DefaultInstance.SignInAnonymouslyAsync().ContinueWith(result =>
{
Debug.Log("LOGIN [ID: " + result.Result.UserId + "]");
userID = result.Result.UserId;
FirebaseDatabase.DefaultInstance.GetReference("GlobalMsgs/").ChildAdded += HandleNewsAdded;
FirebaseDatabase.DefaultInstance.GetReference("Users/" + userID + "/infodata/nickname/").ValueChanged += HandleNameChanged;
FirebaseDatabase.DefaultInstance.GetReference("Users/" + userID + "/staticdata/status/").ValueChanged += HandleStatusChanged;
FirebaseDatabase.DefaultInstance.GetReference("Lobbies/").ChildAdded += HandleLobbyAdded;
FirebaseDatabase.DefaultInstance.GetReference("Lobbies/").ChildRemoved += HandleLobbyRemoved;
loggedIn = true;
});
And then get values.
DI.ContinueWith(Task =>
{
FirebaseDatabase.DefaultInstance.GetReference("Lobbies/" + selectedLobbyID + "/players/").GetValueAsync().ContinueWith((result) =>
{
DataSnapshot snap2 = result.Result;
Debug.Log("Their nickname is! -> " + snap2.Child("nickname").Value.ToString());
Debug.Log("Their uID is! -> " + snap2.Key.ToString());
//Add the user ID to the lobby list we have
foreach (List<string> lobbyData in onlineLobbies)
{
Debug.Log("Searching for lobby:" + lobbyData[0]);
if (selectedLobbyID == lobbyData[0].ToString()) //This is the id of the user hosting the lobby
{
Debug.Log("FOUND HOSTS LOBBY ->" + lobbyData[0]);
foreach (DataSnapshot snap3 in snap2.Children)
{
//add the user key to the lobby
lobbyData.Add(snap3.Key.ToString());
Debug.Log("Added " + snap3.Child("nickname").Value.ToString() + " with ID: " + snap3.Key.ToString() + " to local lobby.");
currentUsers++;
}
return;
}
}
});
});
Obviously you can alter it how you like, It does not really need loops but i'm using them to test before i compact the code into something less readable and more intuitive.
I'm having issues creating an asynchronous web service using the Task Parallel Library with ASP.NET Web API 2. I make an asynchronous call to a method StartAsyncTest and create a cancellation token to abort the method. I store the token globally and then retrieve it and call it from a second method CancelAsyncTest. Here is the code:
// Private Global Dictionary to hold text search tokens
private static Dictionary<string, CancellationTokenSource> TextSearchLookup
= new Dictionary<string, CancellationTokenSource>();
/// <summary>
/// Performs an asynchronous test using a Cancellation Token
/// </summary>
[Route("StartAsyncTest")]
[HttpGet]
public async Task<WsResult<long>> StartAsyncTest(string sSearchId)
{
Log.Debug("Method: StartAsyncTest; ID: " + sSearchId + "; Message: Entering...");
WsResult<long> rWsResult = new WsResult<long>
{
Records = -1
};
try
{
var rCancellationTokenSource = new CancellationTokenSource();
{
var rCancellationToken = rCancellationTokenSource.Token;
// Set token right away in TextSearchLookup
TextSearchLookup.Add("SyncTest-" + sSearchId, rCancellationTokenSource);
HttpContext.Current.Session["SyncTest-" + sSearchId] =
rCancellationTokenSource;
try
{
// Start a New Task which has the ability to be cancelled
var rHttpContext = (HttpContext)HttpContext.Current;
await Task.Factory.StartNew(() =>
{
HttpContext.Current = rHttpContext;
int? nCurrentId = Task.CurrentId;
StartSyncTest(sSearchId, rCancellationToken);
}, TaskCreationOptions.LongRunning);
}
catch (OperationCanceledException e)
{
Log.Debug("Method: StartAsyncText; ID: " + sSearchId
+ "; Message: Cancelled!");
}
}
}
catch (Exception ex)
{
rWsResult.Result = "ERROR";
if (string.IsNullOrEmpty(ex.Message) == false)
{
rWsResult.Message = ex.Message;
}
}
// Remove token from Dictionary
TextSearchLookup.Remove(sSearchId);
HttpContext.Current.Session[sSearchId] = null;
return rWsResult;
}
private void StartSyncTest(string sSearchId, CancellationToken rCancellationToken)
{
// Spin for 1100 seconds
for (var i = 0; i < 1100; i++)
{
if (rCancellationToken.IsCancellationRequested)
{
rCancellationToken.ThrowIfCancellationRequested();
}
Log.Debug("Method: StartSyncTest; ID: " + sSearchId
+ "; Message: Wait Pass #" + i + ";");
Thread.Sleep(1000);
}
TextSearchLookup.Remove("SyncTest-" + sSearchId);
HttpContext.Current.Session.Remove("SyncTest-" + sSearchId);
}
[Route("CancelAsyncTest")]
[HttpGet]
public WsResult<bool> CancelAsyncTest(string sSearchId)
{
Log.Debug("Method: CancelAsyncTest; ID: " + sSearchId
+ "; Message: Cancelling...");
WsResult<bool> rWsResult = new WsResult<bool>
{
Records = false
};
CancellationTokenSource rCancellationTokenSource =
(CancellationTokenSource)HttpContext.Current.Session["SyncTest-" + sSearchId];
// Session doesn't always persist values. Use TextSearchLookup as backup
if (rCancellationTokenSource == null)
{
rCancellationTokenSource = TextSearchLookup["SyncTest-" + sSearchId];
}
if (rCancellationTokenSource != null)
{
rCancellationTokenSource.Cancel();
TextSearchLookup.Remove("SyncTest-" + sSearchId);
HttpContext.Current.Session.Remove("SyncTest-" + sSearchId);
rWsResult.Result = "OK";
rWsResult.Message = "Cancel delivered successfully!";
}
else
{
rWsResult.Result = "ERROR";
rWsResult.Message = "Reference unavailable to cancel task"
+ " (if it is still running)";
}
return rWsResult;
}
After I deploy this to IIS, the first time I call StartAsyncTest and then CancelAsyncTest (via the REST endpoints), both requests go through and it cancels as expected. However, the second time, the CancelAsyncTest request just hangs and the method is only called after StartAsyncTest completes (after 1100 seconds). I don't know why this occurs. StartAsyncTest seems to highjack all threads after it's called once. I appreciate any help anyone can provide!
I store the token globally and then retrieve it and call it from a second method CancelAsyncTest.
This is probably not a great idea. You can store these tokens "globally", but that's only "global" to a single server. This approach would break as soon as a second server enters the picture.
That said, HttpContext.Current shouldn't be assigned to, ever. This is most likely the cause of the odd behavior you're seeing. Also, if your real code is more complex than ThrowIfCancellationRequested - i.e., if it's actually listening to the CancellationToken - then the call to Cancel can execute the remainder of StartSyncTest from within the call to Cancel, which would cause considerable confusion over the value of HttpContext.Current.
To summarize:
I recommend doing away with this approach completely; it won't work at all on web farms. Instead, keep your "task state" in an external storage system like a database.
Don't pass HttpContext across threads.
A colleague offered a alternative call to Task.Factory.StartNew (within StartAsyncTest):
await Task.Factory.StartNew(() =>
{
StartSyncTest(sSearchId, rCancellationToken);
},
rCancellationToken,
TaskCreationOptions.LongRunning,
TaskScheduler.FromCurrentSynchronizationContext());
This implementation seemed to solve the asynchronous issue. Now future calls to CancelAsyncTest succeed and cancel the task as intended.
Needless to say I'm new to C# and doing some basic things to learn along the way. I'm trying to understand async/await feature. I have a form with 2 textboxes and a button. When I click the button, it checks a remote computer's service status (in this case remote registry. While it checks, it writes that it is checking the registry and tells the user to wait. Then starts if the state is stopped and gets some values I look for and writes those to the second textbox.
My code works, and I'm able to get my values. But the GUI freezes during this time. I tried to implement backgroundworker, thread and Async/Wait with no success. I tried doing Task and couldn't get that to work.
All the examples shown here or on other sites simply return int while I'm trying to return a string that writes the status and the values I want to textboxes. I tried to convert it to string with no success.
Long story short, for this type of processes, what would be a better approach? Can someone show me how and comment what does what along the way just so I understand better? I want to learn how to do it but at the same time learn why and learn to write cleaner code.
Thank you everyone for taking their time in advance.
string ComputerName = "Lab01";
public frmRegChecker()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
Check_Status();
}
private void Check_Status()
{
TxtBoxstatus.AppendText("Checking Remote Registry service status on computer : " + ComputerName);
TxtBoxstatus.AppendText(Environment.NewLine);
TxtBoxstatus.AppendText("Please wait... ");
ServiceController sc = new ServiceController("RemoteRegistry", ComputerName);
try
{
TxtBoxstatus.AppendText("The Remote Registry service status is currently set to : " + sc.Status.ToString());
TxtBoxstatus.AppendText(Environment.NewLine);
if (sc.Status == ServiceControllerStatus.Stopped)
{
// Start the service if the current status is stopped.
TxtBoxstatus.AppendText("Starting Remote Registry service...");
TxtBoxstatus.AppendText(Environment.NewLine);
try
{
// Start the service, and wait until its status is "Running".
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 3));
sc.Refresh();
sc.WaitForStatus(ServiceControllerStatus.Running);
// Display the current service status.
TxtBoxstatus.AppendText("The Remote Registry status is now set to:" + sc.Status.ToString());
richTextBox1.AppendText(Environment.NewLine);
try
{
var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
var key = reg.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion\");
string _OSVersion = (key.GetValue("CurrentVersion")).ToString();
richTextBox1.AppendText("OS version is : " + _OSVersion);
richTextBox1.AppendText(Environment.NewLine);
}
catch (InvalidOperationException)
{
richTextBox1.AppendText("Error getting registry value from" + ComputerName);
richTextBox1.AppendText(Environment.NewLine);
}
}
catch (InvalidOperationException)
{
richTextBox1.AppendText("Could not start the Remote Registry service.");
richTextBox1.AppendText(Environment.NewLine);
}
}
else if (sc.Status == ServiceControllerStatus.Running)
{
try
{
var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
var key = reg.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion\");
string _OSVersion = (key.GetValue("CurrentVersion")).ToString();
richTextBox1.AppendText("OS version is : " + _OSVersion);
richTextBox1.AppendText(Environment.NewLine);
}
catch (InvalidOperationException)
{
richTextBox1.AppendText("Error getting registry value from" + ComputerName);
richTextBox1.AppendText(Environment.NewLine);
}
}
}
}
catch
{
richTextBox1.AppendText("Error getting registry value from " + ComputerName);
richTextBox1.AppendText(Environment.NewLine);
}
}
Unfortunately, ServiceController is a rather outdated class and doesn't natively support async/await. That would be the cleanest solution if it were possible.
So, what you can do is use async/await with Task.Run. Task.Run executes code on a background thread, and you can use async/await from the UI to consume that background operation. This approach allows exceptions to be propagated and handled in a natural fashion, and it allows return values to also be handled naturally. Strip out the textbox updates for now for simplicity, and the first step looks like this:
private async void Button1_Click(object sender, EventArgs e)
{
try
{
var osVersion = await Task.Run(() => CheckStatus());
richTextBox1.AppendText("OS version is : " + osVersion);
richTextBox1.AppendText(Environment.NewLine);
}
catch (InvalidOperationException ex)
{
richTextBox1.AppendText("Error getting registry value from" + ComputerName);
richTextBox1.AppendText(ex.ToString());
richTextBox1.AppendText(Environment.NewLine);
}
}
private string CheckStatus()
{
ServiceController sc = new ServiceController("RemoteRegistry", ComputerName);
if (sc.Status == ServiceControllerStatus.Stopped)
{
// Start the service if the current status is stopped.
// Start the service, and wait until its status is "Running".
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 3));
sc.Refresh();
sc.WaitForStatus(ServiceControllerStatus.Running);
}
var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
var key = reg.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion\");
return (key.GetValue("CurrentVersion")).ToString();
}
Next, add the progress updates. There's a built-in mechanism for that - IProgress<T>/Progress<T>, and it works like this:
private async void Button1_Click(object sender, EventArgs e)
{
try
{
var progress = new Progress<string>(update =>
{
TxtBoxstatus.AppendText(update);
TxtBoxstatus.AppendText(Environment.NewLine);
});
var osVersion = await Task.Run(() => CheckStatus(progress));
richTextBox1.AppendText("OS version is : " + osVersion);
richTextBox1.AppendText(Environment.NewLine);
}
catch (InvalidOperationException ex)
{
richTextBox1.AppendText("Error getting registry value from" + ComputerName);
richTextBox1.AppendText(ex.ToString());
richTextBox1.AppendText(Environment.NewLine);
}
}
private string CheckStatus(IProgres<string> progress)
{
progress?.Report("Checking Remote Registry service status on computer : " + ComputerName);
progress?.Report("Please wait... ");
ServiceController sc = new ServiceController("RemoteRegistry", ComputerName);
progress?.Report("The Remote Registry service status is currently set to : " + sc.Status.ToString());
if (sc.Status == ServiceControllerStatus.Stopped)
{
// Start the service if the current status is stopped.
progress?.Report("Starting Remote Registry service...");
// Start the service, and wait until its status is "Running".
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 3));
sc.Refresh();
sc.WaitForStatus(ServiceControllerStatus.Running);
progress?.Report("The Remote Registry status is now set to:" + sc.Status.ToString());
}
var reg = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ComputerName);
var key = reg.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion\");
return (key.GetValue("CurrentVersion")).ToString();
}
Note the separation of concerns: the only code that touches UI objects is a UI event handler. The CheckStatus method that contains the actual program logic is separated from the UI - all it knows is that it can report progress strings and return a string result.
This can easily be accomplished using async/await. An Example:
A simple WPF form:
<Window x:Class="WpfApp1.MainWindow"
...>
<Grid>
<Button Name="button" Content="Start" Click="Button_Click"/>
<TextBox Name="textButton" />
</Grid>
</Window>
and the associated code-behind:
public partial class MainWindow:Window
{
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
textButton.Text = "Running...";
string result = await DoIt();
textButton.Text = result;
}
private async Task<string> DoIt()
{
await Task.Delay(3000);
return "Finished...";
}
}
When clicking the button, the long-running 'calculation' in 'DoIt' is started'asynchrounously. While it is running, the UI remains responsive.
When DoIt returns returns its result (in this example after a dummy delay of 3 seconds) the 'click' eventhandler continues...
Remarks:
this example uses code behind for simplicity. The technique works as well using the MVVM-pattern (where the async operation is started from a command).
'async void' is an anti pattern, but is used to comply withe the auto generated eventhandler in code behind.
in a real world application the async 'DoIt' method would propably be situated in a backend 'model class'.
the example assumes you only want to update the UI once the long-running operation has finished. If you want intermediate updates, there are several options (unfortunately a bit more complex).
I think you can still use the backgroundworker to make your textboxes display messages without freezing the GUI. Take reference from this question Here on how to return an object from backgroundworker.
I'm creating a discord bot, and I'm struggling to figure out how to kick a user. I can't find code or documentation on this. Here's the code
private void MuteUserCommand()
{
commands.CreateCommand("stfu")
.Parameter("PersonToKick", ParameterType.Required)
.Do(async (e) =>
{
string persontomute = e.GetArg("PersonToKick");
if (e.User.ServerPermissions.MuteMembers == false)
{
await e.Channel.SendMessage("Yoo cahnot tells " + persontomute + " to shut up, iz not enuff poweh!");
}
else
{
await e.Channel.SendMessage("Shut up " + persontomute + "!");
//How do I kick persontomute here?
}
});
}
Update: I'm using Discord.NET 0.9.6
This is the command I use to kick people, checking for the correct permissions etc. (Make sure the bot has kick permissions itself ofcourse)
_client.GetService<CommandService>().CreateGroup("user", cgb =>
{
cgb.CreateCommand("kick")
.Description("Kick a user from the Server.")
.Parameter("User", ParameterType.Required)
.AddCheck((command, user, channel) => !paused)
.Do(async e =>
{
try
{
if (e.User.ServerPermissions.KickMembers)
{
User user = null;
try
{
// try to find the user
user = e.Server.FindUsers(e.GetArg("User")).First();
}
catch (InvalidOperationException)
{
await e.Channel.SendMessage($"Couldn't kick user {e.GetArg("User")} (not found).");
return;
}
// double safety check
if (user == null) await e.Channel.SendMessage($"Couldn't kick user {e.GetArg("User")} (not found).");
await user.Kick();
await e.Channel.SendMessage($"{user.Name} was kicked from the server!");
}
else
{
await e.Channel.SendMessage($"{e.User.Name} you don't have the permission to kick.");
}
}
catch (Exception ex)
{
// needs a better error handling haven't changed it since i tested it xD
await e.Channel.SendMessage(ex.Message);
}
});
You seem to be using Discord.Net. You need to get the user from the server and then kick them, as explaned in the documentation.
EDIT: my bad, I took this snippet from a friend's bot and forgot it used a custom extension. I added a "vanilla" way, taken straight from the sample bot.
var user = await _client.FindUser(e, e.Args[0], e.Args[1]); //args[0]would be the username, args[1] would be the discriminator (the random number that follows the discord id)
if (user == null) return;
await user.Kick();
Old
string err;
User user = e.Server.Users.FindUser(persontomute, out err);
if(user != null)
{
await user.Kick();
await e.Channel.SendMessage("Shut up " + persontomute + "!");
}
I need to upgrade our service bus nuget package to 3.2.2 (think the evenprocessor host requires it) but I have always kept our service bus project lib at 2.8.2. This is mainly due to the fact that BeginReceive() and EndReceive() looks to have been removed. Is there any reason or anyway I can easily convert this
public void StartReceiving(RecieverCallback callback, TimeSpan waittime, object state = null)
{
this._recieverCallback = callback;
_queueClient = this.MessagingFactory.CreateQueueClient(QueueName, ReceiveMode);
// make initial async call
_asyncresult = _queueClient.BeginReceive(waittime, ReceiveDone, _queueClient);
}
public void ReceiveDone(IAsyncResult result)
{
if (result != null)
{
try
{
var tmpClient = result.AsyncState as QueueClient;
var brokeredMessage = tmpClient.EndReceive(result);
if (brokeredMessage != null)
{
if (ReceiveMode == ReceiveMode.PeekLock)
{
brokeredMessage.Complete();
}
var tmpMessage = brokeredMessage.GetBody<T>();
ProcessMessageProperties(tmpMessage, brokeredMessage);
_recieverCallback(tmpMessage);
}
}
catch (Exception ex)
{
_logger.Fatal("ReceiveDone: {0}", ex.Message);
Console.WriteLine(ex.Message);
}
}
// do recieve for next message
_asyncresult = _queueClient.BeginReceive(ReceiveDone, _queueClient);
}
Image showing the error
Following image shows what happens if I upgrade servicebus to 3.2.2 which I believe will solve the original error (program running 3.2.2, lib project running 2.8.x)
I figured it out see link
https://gist.github.com/sitereactor/8953583
If anyone has a similar issue, let me know and will post my code but its 95% the same as per the link.