Kindly help me. My idea is to continually print Numeric values form 0 to 1000 using thread concept. In case unexceptionally my application closes, how can I write the code WAITING for currently running thread tasks to complete.
Here by i mention sample code...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.Remoting.Messaging;
using System.IO;
namespace Test_AsyncFactorCaller
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public bool Work()
{
int nSleep = 100;
WriteMessage(string.Format("Going to Thread Sleep State for {0} sec", nSleep));
for (int i = 0; i < nSleep; i++)
{
WriteMessage(string.Format("Sleeping = {0}", i));
Thread.Sleep(1000);
}
WriteMessage("Going to Thread Wakeup State");
return true;
}
public void Work_Done(IAsyncResult result)
{
WriteMessage("Work_Done");
AsyncFactorCaller t = (AsyncFactorCaller)((AsyncResult)result).AsyncDelegate;
bool bResult = t.EndInvoke(result);
WriteMessage(string.Format("Result {0}",bResult));
result.AsyncWaitHandle.Close();
}
public void WriteMessage(string sMessage)
{
using (StreamWriter sw = new StreamWriter(#"C:\ThreadLog.txt", true))
{
sw.WriteLine(sMessage);
sw.Close();
}
}
private void btn_asyncCaller_Click(object sender, EventArgs e)
{
try
{
AsyncFactorCaller dGate_caller = new AsyncFactorCaller(Work);
AsyncCallback Completed_callBack = new AsyncCallback(Work_Done);
AsyncOperation asyncOperation = AsyncOperationManager.CreateOperation(null);
IAsyncResult result = dGate_caller.BeginInvoke(Completed_callBack, "Test thread");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
public delegate bool AsyncFactorCaller();
}
}
If you are really sure that this is what you need to do, try using a WaitHandle.
AutoResetEvent _blocker = new AutoResetEvent(false);
//In background thread
_blocker.Set();
//Where you want to wait for it
_blocker.WaitOne();
Related
I am launching another process (node.exe) in order to capture its output and display it in my own Winforms window. The idea is that I'll be able to automatically restart the process if the node server crashes. The code included is just test code, not final code, and it does not kill the process so if you run it, you'll need to kill the node process manually after closing the form.
My problem is that although I am correctly redirecting the output and error streams, there are some funny characters that don't display on the normal console. How do I change it to correctly detect the encoding and display properly?
Here's a sample of output (with some garbage characters at the beginning of each string).
[32m[2014-11-26 08:24:21.525] [INFO] console - [39mExpress server listening on port 8080
Here's the code to launch the process, and redirect the output:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
namespace AHVMonitor
{
enum Output
{
StandardOutput,
StandardError
}
public sealed class ProcessWatcher
{
private ConcurrentQueue<string> logLines = new ConcurrentQueue<string>();
private Process process;
private string arguments = ConfigurationManager.AppSettings["Arguments"];
private string filename = ConfigurationManager.AppSettings["Filename"];
public IList<string> Log
{
get { return logLines.ToArray(); }
}
public async Task<bool> WatchAsync()
{
Func<Task<bool>> waitForProcess = async () =>
{
var result = false;
process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.FileName = filename;
process.StartInfo.Arguments = arguments;
process.StartInfo.WorkingDirectory = Path.GetDirectoryName(filename);
// Hide the (empty) console window, since we are redirecting the output.
process.StartInfo.CreateNoWindow = true;
process.Start();
await TaskExtensions.ForAsync(0, 3, 3, async i =>
{
switch (i)
{
case 0:
await RedirectStandardErrorOrOutputAsync(Output.StandardOutput);
break;
case 1:
await RedirectStandardErrorOrOutputAsync(Output.StandardError);
break;
case 2:
result = await Task.Run(() =>
{
try
{
process.WaitForExit();
return process.ExitCode == 0;
}
catch { return false; }
finally
{
process.Dispose();
process = null;
}
});
break;
}
});
return result;
};
return await waitForProcess();
}
private async Task RedirectStandardErrorOrOutputAsync(Output outputType)
{
using (var reader = new StreamReader(outputType == Output.StandardError ? process.StandardError.BaseStream : process.StandardOutput.BaseStream))
{
var line = string.Empty;
while ((line = await reader.ReadLineAsync()) != null)
logLines.Enqueue(line);
}
}
}
}
For that code to work, you need these two extensions for my ForAsync on the 3 Tasks. (wraps a ForEachAsync implementation not written by me.)
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace AHVMonitor
{
public static class TaskExtensions
{
#region IEnumerable<T>.ForEachAsync and IEnumerable<T>.ForAsync
/// <summary>A ForEachAsync implementation. Based on a sample in an article by Stephen Toub,
/// <a href="http://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx">
/// Implementing a simple ForEachAsync, part 2</a>.</summary>
public static Task ForEachAsync<T>(this IEnumerable<T> source, int maxDegreeOfParallelism, Func<T, Task> body)
{
return Task.WhenAll(
from partition in Partitioner.Create(source).GetPartitions(maxDegreeOfParallelism)
select Task.Run(async () =>
{
using (partition)
while (partition.MoveNext())
await body(partition.Current);
}));
}
/// <summary>An asynchronous ForAsync implementation.</summary>
/// <remarks>It simply creates an <b>Enumerable.Range</b> and wraps <b>ForEachAsync</b>.</remarks>
public static Task ForAsync(int fromInclusive, int toExclusive, int maxDegreeOfParallelism, Func<int, Task> body)
{
return Enumerable.Range(
fromInclusive, toExclusive).
ForEachAsync(maxDegreeOfParallelism, async i => await body(i));
}
#endregion
}
}
The code of the form that uses the "ProcessWatcher", which contains only a button and a textbox, is this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AHVMonitor
{
public partial class WatcherForm : Form
{
private ProcessWatcher watcher = new ProcessWatcher();
public WatcherForm()
{
InitializeComponent();
}
private void WatcherForm_Load(object sender, EventArgs e)
{
LogAsync();
}
private async void LogAsync()
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(1D));
var lines = watcher.Log;
logTextBox.Lines = lines.ToArray();
logTextBox.SelectionStart = logTextBox.TextLength;
logTextBox.ScrollToCaret();
}
}
private async void startButton_Click(object sender, EventArgs e)
{
await watcher.WatchAsync();
}
}
}
That "garbage" looks like escape codes for setting colors, missing the unprintable character ESC (0x1B).
I want to create a method which makes my application wait X number of seconds, then continues on down a line of scripts. For example, this is the code that I have so far, after reading many similar help topics:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
methods.WriteTextToScreen(label1, "Hello!");
methods.sleepFor(1);
methods.WriteTextToScreen(label1, "Welcome!");
methods.sleepFor(1);
methods.WriteTextToScreen(label1, "Allo!");
}
public class methods
{
public static int timeSlept;
public static void WriteTextToScreen(Label LabelName, string text)
{
LabelName.Text = text;
}
public static void sleepFor(int seconds)
{
timeSlept = 0;
System.Timers.Timer newTimer = new System.Timers.Timer();
newTimer.Interval = 1000;
newTimer.AutoReset = true;
newTimer.Elapsed += new System.Timers.ElapsedEventHandler(newTimer_Elapsed);
newTimer.Start();
while (timeSlept < seconds)
{
Application.DoEvents();
}
Application.DoEvents();
}
public static void newTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timeSlept = IncreaseTimerValues(ref timeSlept);
Application.DoEvents();
}
public static int IncreaseTimerValues(ref int x)
{
int returnThis = x + 1;
return returnThis;
}
}
}
}
What I want to do is have my program do the methods.WriteTextToScreen(label1, "Hello!")
then wait for 1 second, then continue on in the same fashion. The problem is that the Form I'm displaying the text on doesn't show up at all until it has written "Allo!" onto the screen, so the first time it appears it already says that. Am I doing something wrong, or is there just no way to do this?
The form doesn't show until it has been constructed i.e. all the code in Form1 is run. See here for info on form constructors: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.form.aspx
To fix your problem you could move the writeTextToScreen and sleep code into the forms on load method. See http://msdn.microsoft.com/en-us/library/system.windows.forms.form.onload.aspx
Delay.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace LearnThread
{
class Delay
{
public int Convert()
{
int ErrorCode = 1;
//something
//takes long time. about 9 hours.
return ErrorCode;
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace LearnThread
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
Delay delay = new Delay();
Thread t = new Thread(delay.Convert);
//something
MessageBox.Show("Success");
}
}
}
Delay delay = new Delay(); is error here as it is expecting return value. I want the return value as it is contains errorcode. How can I do that? Background worker is better than Thread? Please help. (I should not lose control on the form when delay.Convert() is running.)
As mentioned by Juergen, you can make ErrorCode a class member and then access it once the thread has completed execution. This would require you to create a new instance of the Delay class if you are trying to run multiple Convert in parallel.
You can also use a delegate to get the return value to a variable in the btnStart_Click function as follows:
private void button1_Click(object sender, EventArgs e)
{
Delay delay = new Delay();
int delayResult = 0;
Thread t = new Thread(delegate() { delayResult = delay.Convert(); });
t.Start();
while (t.IsAlive)
{
System.Threading.Thread.Sleep(500);
}
MessageBox.Show(delayResult.ToString());
}
If you plan to run Convert in parallel here, you would have to create as many local variable as required or handle it someother way.
Make the ErrorCode a class member. This way you can get it afterwards.
class Delay
{
public int ErrorCode { get; private set; }
public void Convert()
{
ErrorCode = 1;
...
}
}
private void btnStart_Click(object sender, EventArgs e)
{
Delay delay = new Delay();
Thread t = new Thread(delay.Convert);
//something
int error = delay.ErrorCode;
MessageBox.Show("Success");
}
My question is all about URL Protocols.
I have registered a URL Protocol called mcm, but I noticed that everytime I run it from any web browser, t creates a new instance of the application. Is there any way to handle the protocol request in an already running instance?
For example, when uTorrent is using the torrent protocol It handles the request immediately without running the app again. I couldn't really find anything interesting about it, so I am asking here...
Here is the code I use to register the protocol:
private static void RegisterUrlProtocol()
{
UnregisterUrlProtocol();
RegistryKey rKey = Registry.ClassesRoot.OpenSubKey(UrlProtocol, true);
if (rKey == null)
{
rKey = Registry.ClassesRoot.CreateSubKey(UrlProtocol);
rKey.SetValue("", "URL: MazCraft Protocol");
rKey.SetValue("URL Protocol", "");
rKey = rKey.CreateSubKey(#"shell\open\command");
rKey.SetValue("", "\"" + Application.ExecutablePath + "\" %1");
}
if (rKey != null)
{
rKey.Close();
}
}
And the code to read the arguments:
private static bool CheckForProtocolMessage()
{
string[] arguments = Environment.GetCommandLineArgs();
if (arguments.Length > 1)
{
string[] args = arguments[1].Split(':');
args[1] = args[1].Replace("//", "");
if (args[0].Trim().ToUpper() == "MCM" && args.Length > 1)
{
string[] actionDetail = args[1].Split('=');
if (actionDetail[0].Trim().ToUpper() == "INSTALL" && actionDetail.Length > 1)
{
string id = actionDetail[1].Trim().Replace("/", "");
Funcs.ID = id;
return true;
}
}
}
return false;
}
Any help would be greatly appreciated :)
Greetings.
You could use a Mutex to detect an instance of the application that is already running and send the data over to the existing instance via Named Pipes.
Hope the following example helps.
you can swap out the named pipes object (in this case string) for whatever serializable object you like.
NamedPipe.cs
namespace SingleInstanceNP
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
using System.IO;
public class NamedPipe<T> : IDisposable
{
#region Attribute and Properties
private string _pipeName;
private NamedPipeServerStream _pipeServer;
private bool _disposed;
private Thread _thread;
private bool _started;
#endregion
#region Constructors
public NamedPipe(NameTypes pipeType)
{
_disposed = false;
_started = false;
_pipeName = pipeType.ToString();
_thread = new Thread(Main);
_thread.SetApartmentState(ApartmentState.STA);
_thread.Name = "NamePipe: " + pipeType.ToString() + " Thread";
_thread.IsBackground = true;
}
~NamedPipe()
{
Dispose();
}
#endregion
#region Events
public delegate void Request(T t);
public event Request OnRequest;
#endregion
#region Public Methods
public static void Send(NameTypes pipeType, T t)
{
using (var npc = new NamedPipeClientStream(".", pipeType.ToString(), PipeDirection.Out))
{
var bf = new BinaryFormatter();
npc.Connect();
bf.Serialize(npc, t);
}
}
public static T Recieve(NameTypes pipeType)
{
using (var nps = new NamedPipeServerStream(pipeType.ToString(), PipeDirection.In))
{
return Recieve(nps);
}
}
public void Start()
{
if (!_disposed && !_started)
{
_started = true;
_thread.Start();
}
}
public void Stop()
{
_started = false;
if (_pipeServer != null)
{
_pipeServer.Close();
// disposing will occur on thread
}
}
public void Dispose()
{
_disposed = true;
Stop();
if (OnRequest != null)
OnRequest = null;
}
#endregion
private void Main()
{
while (_started && !_disposed)
{
try
{
using (_pipeServer = new NamedPipeServerStream(_pipeName))
{
T t = Recieve(_pipeServer);
if (OnRequest != null && _started)
OnRequest(t);
}
}
catch (ThreadAbortException)
{ }
catch (System.IO.IOException iox)
{
Console.WriteLine("ERROR: {0}", iox.Message);
Thread.Sleep(TimeSpan.FromSeconds(30));
}
catch (Exception ex)
{
Console.WriteLine("ERROR: {0}", ex.Message);
return;
}
}
}
private static T Recieve(NamedPipeServerStream nps)
{
var bf = new BinaryFormatter();
try
{
nps.WaitForConnection();
var obj = bf.Deserialize(nps);
if (obj is T)
return (T)obj;
}
// Catch the IOException that is raised if the pipe is
// broken or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
return default(T);
}
#region Enums
public enum NameTypes
{
PipeType1
}
#endregion
}
}
Program.cs
Please give credit for the APP GUID to What is a good pattern for using a Global Mutex in C#?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Threading;
namespace SingleInstanceNP
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// get application GUID as defined in AssemblyInfo.cs
string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
// unique id for global mutex - Global prefix means it is global to the machine
string mutexId = string.Format("Global\\{{{0}}}", appGuid);
using (var mutex = new Mutex(false, mutexId))
{
try
{
if (!mutex.WaitOne(0, false))
{
//signal existing app via named pipes
NamedPipe<string>.Send(NamedPipe<string>.NameTypes.PipeType1, "test");
Environment.Exit(0);
}
else
{
// handle protocol with this instance
Application.Run(new Form1());
}
}
finally
{
mutex.ReleaseMutex();
}
}
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace SingleInstanceNP
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// start listening for named pipe connections
var namedPipeString = new NamedPipe<string>(NamedPipe<string>.NameTypes.PipeType1);
namedPipeString.OnRequest += new NamedPipe<string>.Request(namedPipeString_OnRequest);
namedPipeString.Start();
}
void namedPipeString_OnRequest(string t)
{
MessageBox.Show(t);
}
}
}
This program is writing numbers from 1 to 5000 in thread, but main form freezes anyway.
Where is an error? Thanks in advance.
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Threading;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
int how, current;
bool job;
Object lockobj = new Object();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Started!");
how = 5000;
current = 0;
job = true;
Thread worker = new Thread(Go);
worker.Name = "1";
worker.Start();
}
private void Go()
{
while (job)
{
if (current < how)
{
lock (lockobj)
{
current++;
}
log(string.Format("Thread #{0}: {1}", Thread.CurrentThread.Name, current));
}
else
{
job = false;
}
}
}
private void log(string text)
{
Action A = new Action(() =>
{
richTextBox1.AppendText(text + System.Environment.NewLine);
});
if (richTextBox1.InvokeRequired)
this.BeginInvoke(A);
else A();
}
}
}
Because most of your work will be spent in
if (richTextBox1.InvokeRequired)
this.BeginInvoke(A);
and while you invoke the form it is locked.
Do some real work, like Thread.Sleep(1000); :-) , instead of current++; and your form will be response between the updates.
It freezes because you are rendering on the textbox very quickly and the GUI doesn't have time to keep in sync. Remember that this rendering happens on the main GUI thread and by calling BeginInvoke to update the textbox so rapidly actually consumes all the resources of this main GUI thread. Try lowering the frequency at which you are logging to avoid this behavior.