I'm handling local requests by using FiddlerCore. All sessions are queued in Queue<Session> and processed by a BackgroundWorker. After the process is done, I would like to send a response, indicating the success or failure of the processing, by using the processed session. The problem is that I'm getting the Too late, we're already talking to the server error.
This is the FiddlerCore function:
private static void FiddlerApplication_BeforeRequest(Session session)
{
if (session.hostname.ToLower() == "localhost")
{
LogHelper.WriteFormat("Local request {0} enqueued", session.id);
sessionsQueue.Enqueue(session);
if (!sessionWorker.IsBusy)
sessionWorker.RunWorkerAsync();
}
}
This is the thread function:
private static void sessionWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (sessionsQueue.Count > 0)
{
if (sessionWorker.CancellationPending)
{
e.Cancel = true;
sessionsQueue.Clear();
LogHelper.Write("Shutting down, all requests canceled");
break;
}
currentSession = sessionsQueue.Dequeue();
LogHelper.WriteFormat("Processing request ID {0}", currentSession.id);
ProcessSession();
}
}
This is the code at the end of the ProcessSession function:
{
...
currentSession.bBufferResponse = true;
currentSession.utilCreateResponseAndBypassServer();
currentSession.oResponse.headers.HTTPResponseStatus = "200 OK";
currentSession.oResponse["Content-Type"] = "text/html; charset=UTF-8";
currentSession.oResponse["Cache-Control"] = "private, max-age=0";
currentSession.utilSetResponseBody(responseBody);
}
I've tried to tamper with the session's timers and state, but without success.
The exception in question occurs when you call utilCreateResponseAndBypassServer after having already sent the request to the server. If you want to use the utilCreateResponseAndBypassServer method, you must do so inside the BeforeRequest handler, not at some future time. Similarly, setting bBufferResponse after having already connected to the server is pointless.
Based on your later remarks, you have a misunderstanding about how threading works with FiddlerCore. FiddlerCore processes Sessions on background threadpool threads.
When BeforeRequest fires, your code has a chance to run. If you call utilCreateResponseAndBypassServer inside that method, then the response you generate is immediately returned to the client.
If you don't call utilCreateResponseAndBypassServer inside BeforeRequest, the request is immediately sent to the server by FiddlerCore, and the response is returned to the client when it's available.
To achieve what you're describing, you should NOT try to do your own threading-- instead do all of your work on the thread that goes into the BeforeRequest method and don't leave that method without generating the desired response. You don't need to worry about hanging the UI or anything like that, because BeforeRequest is running on a background thread. The only thing you must do is the Invoke methods if any of your code needs to interact with any UI owned by the UI thread.
Related
I have a number of web posts inside my application that need to send text data to a server but other than awaiting completion of the post shouldnt hold up the methods that are called from (large data posts that would slowdown logic etc that shouldnt be).
Currently im discarding the task as that appeared to be the correct method however on the server end logs indicate it seams to be closing the connection before the data is successfuly sent meaning I'm loosing most of the data in transit.
private void DoSomethingandPost()
{
BeforeMethod();
PushWebDataAsync(TheData1);
PushWebDataAsync(TheData2);
AfterMethod();
}
public static async void PushWebDataAsync(string Data)
{
...makes changes to the data...
try
{
_ = pushDataAync(Data);
}
catch (Exception e)
{
_ = pushDataAync(Data);
}
}
public System.Threading.Tasks.Task<System.Xml.XmlNode> pushDataAync(string Data)
{
return base.Channel.pushDataAync(Data);
}
My gut feeling is that if "AfterMethod" returns before the data has completed sending the connection to the server is cut and so the data isnt fully transmitted.
What Im trying to acheieve really is DoSomethingandPost() completes and exits but the two async Post's continue on their own until complete then exit.
If AfterMethod must run after the two PushWebDataAsync calls, then make the later return a Task, make AfterMethod async and await the push-methods. DoSomethingandPost will return at the first await-statement, doing the rest of the work at some later time . If you want to do the push concurrently then do
var task1 = PushWebDataAsync(TheData1);
var task2 = PushWebDataAsync(TheData2);
await Task.WhenAll(new []{task1, task2});
...
It is good practice to avoid async void since this makes it impossible for the caller to know if the call succeeded or not. If you know this will never be needed, like in the event handler for a button, then it is good practice to handle any exception that may be thrown.
I have a simple console application as follows:
private static void Main (string [] args)
{
System.Console.WriteLine("Initializing context...");
Database.Context.Initialize();
System.Console.WriteLine("Creating server...");
var server = new Server();
server.OnStarting += Server_OnStarting;
server.OnStarted += Server_OnStarted;
System.Console.WriteLine("Starting server...");
server.Start();
}
private static void Server_OnStarting (object sender, EventArgs e)
{
System.Console.WriteLine("Server_OnStarting.");
}
private static void Server_OnStarted (object sender, EventArgs e)
{
System.Console.WriteLine("Server_OnStarted.");
}
SERVER START METHOD:
public bool Start ()
{
bool result = false;
lock (this._SyncRoot)
{
if (!this.Running)
{
this.Stopwatch.Reset();
this.RaiseOnStarting();
this.Running = true;
this.Terminate = false;
this.ThreadObject = new System.Threading.Thread(new System.Threading.ThreadStart(this.ProcessInternal));
this.Stopwatch.Restart();
this.ThreadObject.Start();
this.RaiseOnStarted();
result = true;
}
}
return (result);
}
OUTPUT:
Out of the three Console.WriteLine calls in Main, only the first gets printed immediately. This is understandable since everything in Database.Context.Initialize happens on the same thread. However, the printing of Creating server... and Starting server... are delayed and clump together with the Server_OnStarting and Server_OnStarted messages. The call to the constructor is not threaded but the call to server.Start internally launches a thread, initializes some sockets, etc. However, the events OnStarting and OnStarted are fired on the SAME thread so the threading aspect of it SHOULD NOT matter.
It seems, that after Initializing context... is printed, no matter where I put the call to Console.WriteLine, it does not update the console window until server.Start returns after firing both events.
Is there a way to force the console to update while waiting for the server to start?
Is there a way to force the console to update while waiting for the server to start?
The console behaves this way by default; in fact, there is no (supported) mechanism to force it to behave differently. When the Console.Out property is initiated, the AutoFlush property of the underlying TextWriter is set to true. The documentation for AutoFlush indicates this explicitly (emphasis added):
For example, set AutoFlush to true when you are writing to a device where the user expects immediate feedback. Console.Out is one of these cases: The StreamWriter used internally for writing to Console flushes all its internal state except the encoder state after every call to StreamWriter.Write.
(Note the AutoFlush cannot be queried directly since the actual implementation uses a thread-safe wrapper; however, you can use the debugger or reflection to check that the value of ((Console.Out as TextWriter.SyncTextWriter)._out as StreamWriter).AutoFlush is true.)
Back to the original problem:
It seems, that after Initializing context... is printed, no matter where I put the call to Console.WriteLine, it does not update the console window until server.Start returns after firing both events.
Let's look at what Server.Start actually does:
Enters a lock (presumably non-blocking since the server is not started)
** Raises OnStarting event**
Starts a thread
Restarts a stopwatch
** Raises OnStarted event**
Returns
None of these tasks are particularly intensive. The delay between the OnStarting and OnStarted invocations is likely to be in the microsecond range.
The three status messages will appear to be printed simultaneously because no appreciable time elapses between the instantiation of the server, entering Server.Start method, and returning from Server.Start method.
I am not really sure how thread works.
Here is my code. Upon clicking a send button:
protected void BtnSend_Click(object sender, EventArgs e)
{
Thread threadA = new Thread(SendSMS);
threadA.Start();
}
protected void SendSMS()
{
//some validations here
Thread threadB = new Thread(loadingScreen);
threadB.Start();
threadB.Join();
//code that actually sends the required Mail
threadB.Stop();
loading.Visible = false;
}
threadB is calling this method which is basically a div (called loading) with a loading div that disables user from pressing anything on screen:
protected void loadingScreen()
{
loading.Visible = true;
}
Now the mail is being sent but the loading screen (div) is not becoming visible.
What am I doing wrong?
You have to rethink when you're writing ASP.NET vs. a rich client application. In short (really really short) the web browser (client) sends a request to the server. The server handles that request (that part is your code behind), and returns a result to the web browser.
When you show a DIV in your codebehind, do some work, then hide it again, only the result will arrive at the web browser.
There are multiple ways to achieve the optical effect you want, but you must know about the Life Cycle of ASP.NET first. Start here, for example.
I think you want a responseable application while you compute a huge task.
In WinForms you have to be careful because if you want to change some UI like a Text in a Label you have to synchronize both Threads. (UI-Thread and Thread1)
If you are running .NET 4.0 you should use the Task-Class, because there you don't need to synchronize and you can also use anonymous methods.
protected void SendSMS()
{
loading.Visible = true;
var task = Task.Factory.StartNew(()=>{//code that actually sends the required Mail}
task.Wait();
loading.Visible = false;
}
Actually the loading Gets visible and then hidden quickly. Join returns immediately as soon as it enabled the Div and then the email is sent, the Div is disabled again. Sending email and disabling happens in same thread.
Why do you use threadB? You can do operation only with threadA:
protected void SendSMS()
{
//some validations here
loading.Visible = false;
//code that actually sends the required Mail
loading.Visible = false;
}
Warning for crossthread operation exception.
I have a WPF application where the user enters database information in some textboxes. Once the user clicks "connect", a connection string is created from what the user had entered and a connection is established. I noticed that if the user enters any info that is wrong, the application will hang until the connection times out. By hang, I mean the user can't interact with the rest of the application at all.
It is my goal to keep the application responsive while the connection string is tested.
I thought that putting this workflow on a different thread is a good solution. My idea is to just disable anything that may need a database connection while the thread runs. Once the thread comes back (and has has confirmed the connection string to be valid) I would re-enable everything. Otherwise, leave everything disabled.
However, the Thread class doesn't have an event notification when the thread is done (or at least I am unaware of one).
I have also worked with the BackgroundWorker class. This works better. However, when the RunWorkerCompletedEventHandler event is fired and the connection string isn't valid, I get the following exception:
The calling thread cannot access this object because a different
thread owns it.
This is probably because the connection still hasn't timed out when the completed event handler is fired.
Does anybody have any ideas, or should I just NOT try to multithread a connection to a database?
A code outline of what I am doing:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
dbTool = new DBTool();
// Create the connection string
e.Result = dbTool.connectToDB(); // connectToDB() returns a bool (true if connection established)
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// connectToDB() returns a bool (true if connection established)
if(e.Result == true) // Trying to read e.Result here throws the exception
{
// e.Error and e.Cancel should be checked first
// However, I would like the thread to finish before
// this event is fired
}
if (e.Error != null)
{
Console.WriteLine(e.Error.Message);
}
}
Don't preserve your DbConnection object in a single global variable and share it between threads.
The .NET environment will automatically pool your connections and share them, so calling new DbConnection() is very fast.
You should keep the connection string in a global variable, but then create connections as required on each thread.
EDIT: The original poster may have actually wanted ideas on how to keep the WinForms application responsive while a connection string is being tested. In that case, you want to spawn a different thread to test the connection. From the "connection test thread," you can update the UI by following this pattern - How to update the GUI from another thread in C#?
public void TestConnectionThread(String connstr_to_test)
{
// Notify the user that we're doing our test
string message = "Testing...";
lblTestResultMessage.SetPropertyThreadSafe(() => lblTestResultMessage.Text, message);
try {
dbTool = new DBTool();
message = dbTool.connectToDB();
// If something failed, show a useful debugging message
} catch (Exception ex) {
message = ex.ToString();
}
// Use a lambda expression to communicate results to the user safely
lblTestResultMessage.SetPropertyThreadSafe(() => lblTestResultMessage.Text, message);
}
From DBConnection's documentation:
Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.
In other words, different threads should never share a database connection, because the instance cannot safely be shared. As Ted Spence suggests, you should instead create connections only as you need them (and .Dispose() them when you're done with them). .NET has a built in connection pooling mechanism that does a very good job of making sure connections are reused when possible, but holding onto connections any longer than is absolutely necessary can interfere with its ability to do that.
try
dbtool tool = e.result as dbtool;
If you have a variable in dbTool that that gets set to true or false when the query completes then you should be able to call
tool.variable = true/false
Thank you everyone for your input.
I was able to come up with a solution. After coming across Working With The WPF Dispatcher. I determined that you can obtain the UI thread's Dispatcher object:
//...
dbTool = new DBTool();
// Initialize the connection string
// Disable some UI
Thread thread = new Thread(new ThreadStart(
delegate()
{
dbTool.connectToDB();
UIControl.Dispatcher.BeginInvoke(
new Action(
update
));
}
));
thread.Start();
//.....
void update()
{
if (dbTool.validString) // If the connection string was valid
{
// Re-enable controls
}
else // Invalid connection string
{
// Keep controls disabled if no connection could be created
}
}
This indeed will test the connection string on a different thread, leaving the rest of the application responsive.
I need to write some code that uses TcpListener. The object that using the TcpListener has 3 possibilities: Listen, Stop Listen, Send message. This is how my code looks:
public class someClass
{
public bool listenerEnable {get; set; }
public void StartListen()
{
.
.
.
while (listenerEnable)
{
// Block until client connected
TcpClient client = server.AcceptTcpClient();
// code that doing something with the client message ...
}
}
}
Now, I'm not sure I know how I can keep the thread safe when I want to stop the listener state (change the listenerEnable to be false).
Also I'm not sure I know how to keep this thread safe when I want to send some message to the client (in some separated method) without stopping the server listener state.
Thanks for any help.
I would suggest waiting on an event rather than waiting on a variable. In your current scheme, consider the case when your loop test for whether listener variable is true. If it is it enters the loop and waits for a incoming connection, and blocks. So now even if another thread sets the listener variable to be false, your loop will not exit till someone connects to it and it processes that connection.
One way of working around the problem above will be to have code like:
WaitHandle[] waitHandles = new WaitHandle[] {endlLoopEvent};
while(true)
{
int ret = WaitHandle.WaitAny(waitHandles, 100);
if(WaitTimeout == ret) continue;
else if(0 == ret) break; //our event has been signaled.
else
{
if(!server.Pending()) continue; //Go back to the loop if no connection pending
TcpClient client = server.AcceptTcpClient();
// You can spawn a thread to service the request.
}
}
Sending would not affect the loop above, provided it is not in response to a request for connection above.
Writing a correct, scalable socket server is not simple - I suggest you find / buy one - this has been done many times before.
To answer your question, your problem is that AcceptTcpClient is a blocking call. You will want to use the APM ( Asyncronous Programming Model ) methods that start with BeginXXX and EndXXXlike MSDN BeginAcceptTcpClient.
These methods don't block threads, but you will have to handle the concurrency.