Real Time signalR in ASP.NET error in .ContainsKey - real-time

I tried to chat with SignalR ised and ASP.Net (VB)
When running, works perfectly with the first user, but the login with another user get an error:
Error: Overflow
Please help, I'm new with realtime applications
Public Overrides Function OnConnected() As Task
Dim myRoomId = "XXXX"
Dim myUserId = IdentityUser.UserCode
SyncLock connections
If Not connections.ContainsKey(myRoomId) Then
connections(myRoomId) = New Dictionary(Of Integer, List(Of String))()
End If
If Not connections(myRoomId).ContainsKey(myUserId) Then ' <<<<<--- Error
connections(myRoomId)(myUserId) = New List(Of String)()
End If
connections(myRoomId)(myUserId).Add(Me.Context.ConnectionId)
End SyncLock
Return MyBase.OnConnected()
End Function

you're locking the object "connections" and trying to change it inside SyncLock which is not allowed.
Use an empty object to lock in SyncLock, it should be public and shared.
Also , you should not use "OnConnect()" event becuase it will fire everytime on hub method call
like this
Private Shared _lock_connections As New Object
Public Overrides Function OnConnected() As Task
Dim myRoomId = "XXXX"
Dim myUserId = IdentityUser.UserCode
SyncLock _lock_connections
If Not connections.ContainsKey(myRoomId) Then
connections(myRoomId) = New Dictionary(Of Integer, List(Of String))()
End If
If Not connections(myRoomId).ContainsKey(myUserId) Then ' <<<<<--- Error
connections(myRoomId)(myUserId) = New List(Of String)()
End If
connections(myRoomId)(myUserId).Add(Me.Context.ConnectionId)
End SyncLock
Return MyBase.OnConnected()
End Function

Related

How can I delete a message by message id with MailKit POP3 client?

I want to use the MailKit Pop3Client to retrieve messages from a POP3 mailbox, and then delete these messages after processing. The retrieval code is something like:
Public Function GetMessages(Optional logPath As String = Nothing) As List(Of MimeMessage)
Dim client As Pop3Client
Dim messages = New List(Of MimeMessage)()
Using client
ConnectPop3(client)
Dim count = client.GetMessageCount()
For i As Integer = 0 To count - 1
Dim msg = client.GetMessage(i)
messages.Add(msg)
Next
End Using
Return messages
End Function
My problem here is in order to delete a message in another message, I need an index, but that is long gone once I exit GetMessages. All I have is the info available on a MimeMessage object, but that has no index property, only MessageId, but in my Delete method, I would have to read all mails again, in order to look up an index value.
Now Pop3Client has a GetMessageUid(int index) method, which returns a mysterious string (looks like int) value with no apparent relation at all to the Mime MessageID, but it seems this is all I have. Then I have to store the MailKit Uid with each message, making my retrieval code something like this, using a dictionary to store uid-message pairs:
Public Function GetMessages(Optional delete As Boolean = False, Optional logPath As String = Nothing) As List(Of MimeMessage)
Dim client As Pop3Client
Dim messages = New Dictionary(Of String, MimeMessage)
Using client
ConnectPop3(client)
Dim count = client.GetMessageCount()
For i As Integer = 0 To count - 1
Dim msg = client.GetMessage(i)
Dim u = client.GetMessageUid(i)
messages.Add(u, msg)
Next
client.Disconnect(True)
End Using
Return messages
End Function
I am really hoping I'm missing something here and what should be a really simple process is indeed simple, but I can't find anything else on my own.
The message UID is the only way to track a message between connections.
The index for a message can change as other messages are deleted.
Your options are:
Delete messages as you're downloading them.
Save the UID so you can come back and delete specific messages later.
It may make more sense if you skim through the POP3 RFC.

Why can't I save this SalesForce Batchable class?

I am currently using the Apex Workbook to refresh my knowledge of SalesForce.
Tutorial #15, Lesson 1: Offers the following code:
global class CleanUpRecords implements Database.Batchable<Object>
{
global final String query;
global CleanUpRecords (String q) {query = q;}
global Database.Querylocator start (Database.BatchableContext BC)
{
return Database.getQueryLocator(query);
}
global void execute (Database.BatchableContext BC, List<sObject> scope)
{
delete scope;
Database.emptyRecycleBin(scope);
}
global void finish(Database.BatchableContext BC)
{
AsyncApexJob a = [
SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email
FROM AsyncApexJob
WHERE Id = :BC.getJobId()
];
// Send an email to the Apex job's submitter
// notifying of job completion.
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
String[] toAddresses = new String[] {a.CreatedBy.Email};
mail.setToAddresses(toAddresses);
mail.setSubject('Record Clean Up Completed ' + a.Status);
mail.setPlainTextBody (
'The batch Apex job processed ' + a.TotalJobItems +
' batches with '+ a.NumberOfErrors + ' failures.'
);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}
}
However, regardless of which development interface (e.g. Force IDE, console, setup) I use, when I try to save this, I get:
Multiple markers at this line
- File only saved locally, not to server
- Save error: CleanUpRecords: Class must implement the global interface method: Iterable<Object> start(Database.BatchableContext) from Database.Batchable<Object>, CleanUpRecords: Class must implement the global interface method: void execute(Database.BatchableContext, LIST<Object>) from
Database.Batchable<Object>
(Or some equivalent, depending upon how I try to save it.)
However, it seems to me the required methods are already there.
What's missing?
Prepare to be frustrated ... there's just one character off.
Your class declaration should be:
global class CleanUpRecords implements Database.Batchable<sObject> {
instead of:
global class CleanUpRecords implements Database.Batchable<Object> {

GWT Async call execution order problem

I have a problem with a throw execution in GWT. So I want to show a simple String list in Client side located on "Server Side". Ok, I have in my Main class this atributes:
private final GreetingServiceAsync greetingService = Util.getInstance(); // This is like > typing GWT.create( GreetingService.class );
public ArrayList songs = new ArrayList();
and in my onModuleLoad() method I have a call to another private method that make the Async call to the Server class:
songs.addAll(getSongsList());
So my getSongsList method is as follow:
public ArrayList<String> getSongsList() {
final int defaultSize = 4;
final ArrayList<String> temp = new ArrayList<String>();
GWT.log("Enter in getSongsLists");
greetingService.greetSongMostPopular(defaultSize,
new AsyncCallback<ArrayList<String>>() {
public void onSuccess(ArrayList<String> result) {
GWT.log("Result is:" + result);
temp.addAll(result);
GWT.log("Case 1 TEMP= " + temp);
}
public void onFailure(Throwable caught) {
// throw new
// UnsupportedOperationException("Not supported yet.");
Window.alert("Error greeting data");
}
});
GWT.log("CASE 2 TEMP = " + temp);
return temp;
}
My problem is that in Case 1 I get
[INFO] [MainModule] - Case 1 TEMP= [Song 1, Song 2, Song 3, Song 4]
but in CASE 2 I get the ArrayList empty!!!
[INFO] [MainModule] - Case 1 TEMP= []
What am I doing wrong?
Thanks in advance!
The call to greetSongsMostPopular is asynchronous. This means that the call begins and the code continues directly to the next line of code, in your case GWT.log("CASE 2 TEMP..."). When this line of code is executed, the results are not yet available and you end up with an empty list.
Later, in the background, onSuccess is called with the results. At this point you should call a function to process the results. You can use a pattern similar to the AsyncCallback class, with an onSuccess and onFailure so the caller of this code can handle both cases, or you can just have the caller pass in their own AsyncCallback instance which would make it a thin wrapper around your greetSongsMostPopular RPC function.
This is normal : the callback is called when your server send the answer but the greetSongMostPopular return imediatly.
The call is asynchronous.
All code must be done in the callback (call a function)
Here is the exact process :
greetingService.greetSongMostPopular is called
temp is empty
the second GWT.log is called : temp is always empty
the getSongsList method return : temp is always empty
the server send the answer to the callback : temp is filled
You are not doing anything wrong. This is expected since you are not dealing with synchronous calls. So the case 2 is only invoked after the asynchronous call returns from the server side.

How to intercept mail messages on a POP3 server

I need an application that will intercept all incoming mail messages and modify them according to some specs.
I am an absolute rookie at this, please detail :)
Try this sample code
Dim _tcpClient As New TcpClient
Dim _networkStream As NetworkStream
Dim _Msg As String
With _tcpClient
.Connect(Me.txtServerIp.Text, Integer.Parse(Me.txtPortNum.Text))
_networkStream = .GetStream
Dim sw As New StreamWriter(_networkStream)
Dim sr As New StreamReader(_networkStream)
If Not CheckError(sr.ReadLine()) Then
sw.WriteLine(String.Format("USER {0}", Me.txtUsername.Text))
sw.Flush()
End If
If Not CheckError(sr.ReadLine()) Then
sw.WriteLine(String.Format("PASS {0}", Me.txtPassword.Text))
sw.Flush()
End If
If Not CheckError(sr.ReadLine()) Then
sw.WriteLine("STAT ")
sw.Flush()
End If
_Msg = sr.ReadLine
Dim MsgCount As String = _Msg.Split(New String() {" "}, _
StringSplitOptions.RemoveEmptyEntries)(1)
If Integer.Parse(Me.lblMsgCount.Text) < Integer.Parse(MsgCount) Then
Me.lblMsgCount.Text = MsgCount
End If
sw.WriteLine("Quit ")
sw.Flush()
sw.Close()
sr.Close()
_networkStream.Close()
_tcpClient.Close()
End With
All incoming messages will be coming on over SMTP.
So, you need to do 1 of 2 things:
If your current server supports it, hook into it's SMTP events, and modify the message before it is passed on to the local intended user.
or
You will need a SMTP proxy service, that sits in front of your real SMTP server.
Inside of the SMTP proxy, modify the message, and pass it on to your real SMTP server.

How to run lengthy tasks from an ASP.NET page?

I've got an ASP.NET page with a simple form. The user fills out the form with some details, uploads a document, and some processing of the file then needs to happens on the server side.
My question is - what's the best approach to handling the server side processing of the files? The processing involves calling an exe. Should I use seperate threads for this?
Ideally I want the user to submit the form without the web page just hanging there while the processing takes place.
I've tried this code but my task never runs on the server:
Action<object> action = (object obj) =>
{
// Create a .xdu file for this job
string xduFile = launcher.CreateSingleJobBatchFile(LanguagePair, SourceFileLocation);
// Launch the job
launcher.ProcessJob(xduFile);
};
Task job = new Task(action, "test");
job.Start();
Any suggestions are appreciated.
You could invoke the processing functionality asynchronously in a classic fire and forget fashion:
In .NET 4.0 you should do this using the new Task Parallel Library:
Task.Factory.StartNew(() =>
{
// Do work
});
If you need to pass an argument to the action delegate you could do it like this:
Action<object> task = args =>
{
// Do work with args
};
Task.Factory.StartNew(task, "SomeArgument");
In .NET 3.5 and earlier you would instead do it this way:
ThreadPool.QueueUserWorkItem(args =>
{
// Do work
});
Related resources:
Task Class
ThreadPool.QueueUserWorkItem Method
Use:
ThreadPool.QueueUserWorkItem(o => MyFunc(arg0, arg1, ...));
Where MyFunc() does the server-side processing in the background after the user submits the page;
I have a site that does some potentially long running stuff that needs to be responsive and update a timer for the user.
My solution was to build a state machine into the page with a hidden value and some session values.
I have these on my aspx side:
<asp:Timer ID="Timer1" runat="server" Interval="1600" />
<asp:HiddenField runat="server" ID="hdnASynchStatus" Value="" />
And my code looks something like:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
PostbackStateEngineStep()
UpdateElapsedTime()
End Sub
Private Sub PostbackStateEngineStep()
If hdnASynchStatus.Value = "" And Not CBool(Session("WaitingForCallback")) Then
Dim i As IAsyncResult = {...run something that spawns in it's own thread, and calls ProcessCallBack when it's done...}
Session.Add("WaitingForCallback", True)
Session.Add("InvokeTime", DateTime.Now)
hdnASynchStatus.Value = "WaitingForCallback"
ElseIf CBool(Session("WaitingForCallback")) Then
If Not CBool(Session("ProcessComplete")) Then
hdnASynchStatus.Value = "WaitingForCallback"
Else
'ALL DONE HERE
'redirect to the next page now
response.redirect(...)
End If
Else
hdnASynchStatus.Value = "DoProcessing"
End If
End Sub
Public Sub ProcessCallBack(ByVal ar As IAsyncResult)
Session.Add("ProcessComplete", True)
End Sub
Private Sub UpdateElapsedTime()
'update a label with the elapsed time
End Sub