Currently I am using the following:
Stopwatch stopWatchB = new Stopwatch();
stopWatchB.Start();
_callIndex.Test = _callTable.Get(u => u.PartitionKey == _callIndex.PageMeta.User & u.RowKey == "A");
stopWatchB.Stop();
em1 = stopWatchB.ElapsedMilliseconds;
My code works great but looks so messy. Stopwatches starting and stopping :-( Is there any way that I could clean this up. Note that I can't change the .Get() method and the data returned to _callIndex.Test is a class called Test that has multiple fields.
Well, to start with you can use:
Stopwatch stopWatchB = Stopwatch.StartNew();
You could also take the ElapsedMilliseconds without stopping it first, if you wanted:
Stopwatch stopWatchB = Stopwatch.StartNew();
_callIndex.Test = _callTable.Get(
u => u.PartitionKey == _callIndex.PageMeta.User & u.RowKey == "A");
em1 = stopWatchB.ElapsedMilliseconds;
That's a bit simpler. Alternatively, you could create a helper method:
public static TimeSpan Time(Action action)
{
Stopwatch stopwatch = Stopwatch.StartNew();
action();
return stopwatch.Elapsed;
}
Then:
em1 = StopwatchHelper.Time(() => {
_callIndex.Test = _callTable.Get(
u => u.PartitionKey == _callIndex.PageMeta.User & u.RowKey == "A");
}).TotalMilliseconds;
I use this to do "benchmark"
for using it:
using(var b = new bench())
{
//stuff
em1 = b.ElapsedMilliseconds;
}
///
class bench : Stopwatch, IDisposable
{
private static bool enabled = true;
public static bool Enabled
{
get { return enabled; }
set { enabled = value; }
}
private string func;
/// <summary>
/// Initializes a new instance of the <see cref="bench"/> class.
/// </summary>
public bench()
{
begin("", false, false);
}
/// <summary>
/// Initializes a new instance of the <see cref="bench"/> class.
/// </summary>
/// <param name="showStack">if set to <c>true</c> [show stack].</param>
public bench(bool showStack)
{
begin("", showStack, false);
}
/// <summary>
/// Initializes a new instance of the <see cref="bench"/> class.
/// </summary>
/// <param name="showStack">if set to <c>true</c> [show stack].</param>
/// <param name="showStart">if set to <c>true</c> [show start].</param>
public bench(bool showStack, bool showStart)
{
begin("", showStack, showStart);
}
/// <summary>
/// Initializes a new instance of the <see cref="bench"/> class.
/// </summary>
/// <param name="func">The func.</param>
public bench(String func)
{
begin(func, false, false);
}
/// <summary>
/// Initializes a new instance of the <see cref="bench"/> class.
/// </summary>
/// <param name="func">The func.</param>
/// <param name="showStack">if set to <c>true</c> [show stack].</param>
public bench(String func, bool showStack)
{
begin(func, showStack, false);
}
/// <summary>
/// Initializes a new instance of the <see cref="bench"/> class.
/// </summary>
/// <param name="func">The func.</param>
/// <param name="showStack">if set to <c>true</c> [show stack].</param>
/// <param name="showStart">if set to <c>true</c> [show start].</param>
public bench(String func, bool showStack, bool showStart)
{
begin(func, showStack, showStart);
}
/// <summary>
/// Begins the specified func.
/// </summary>
/// <param name="func">The func.</param>
/// <param name="showStack">if set to <c>true</c> [show stack].</param>
/// <param name="showStart">if set to <c>true</c> [show start].</param>
private void begin(String func, bool showStack, bool showStart)
{
if (bench.Enabled)
{
this.func = func;
if (showStack || showStart)
Debug.WriteLine("Start " + func);
if (showStack)
Debug.WriteLine("Stack: " + Environment.StackTrace);
this.Start();
}
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
if (bench.Enabled || this.IsRunning)
{
this.Stop();
if (bench.Enabled)
{
Debug.WriteLine("Stop " + func + " " + Elapsed.TotalSeconds.ToString("0.#######") + " seconds");
}
}
}
}
Create a class that implements IDisposable, and starts a stopwatch on creation, stopping it when disposed.
You can create a class that manages such items, as in my code here:
https://stackoverflow.com/questions/6410569/speeding-up-performance-monitoring-code
It does quite a bit more than you ask (handling timing 'child' code and rendering timing values), however you can hopefully get the basic idea.
EDIT: For a simple example, see #Fredou's answer.
You can write the class which starts Stopwatch in the constructor and stops in the Dispose() (obviously you have to implement IDisposable).
using (var profiler = new PerformanceProfiler(out elapsedMilliseconds)
{
// profiled action code ...
}
Debug.WriteLine(elapsedMilliseconds.ToString(CultureInfo.CurrentCulture));
Related
I found a project in Unity 5 where python can be run in Unity, and i want to add libraries to it. The trouble is, i can't seem to find where the python libraries from this script. To me, it looks like they're being generated out of thin air. Can i have a pointer as to where this might be coming from? I tried adding it to python path, and its not seeming to work.
using System;
using System.IO;
using System.Linq;
using UnityEngine;
using System.Text;
using System.Collections;
using IronPython.Hosting;
using IronPython.Modules;
using System.Collections.Generic;
using Microsoft.Scripting.Hosting;
/// <summary>
/// Interpreter for IronPython.
/// </summary>
public class Interpreter
{
/// <summary>
/// The scope.
/// </summary>
private ScriptScope Scope;
/// <summary>
/// The engine.
/// </summary>
private ScriptEngine Engine;
/// <summary>
/// The source.
/// </summary>
private ScriptSource Source;
/// <summary>
/// The compiled.
/// </summary>
private CompiledCode Compiled;
/// <summary>
/// The operation.
/// </summary>
private ObjectOperations Operation;
/// <summary>
/// The python class.
/// </summary>
private object PythonClass;
/// <summary>
/// Initializes a new instance of the <see cref="Interpreter"/> class.
/// </summary>
public Interpreter()
{
Engine = Python.CreateEngine();
Scope = Engine.CreateScope();
SetLibrary();
}
/// <summary>
/// Initializes a new instance of the <see cref="Interpreter"/> class.
/// </summary>
/// <param name="source">Source.</param>
public Interpreter(string src) : this()
{
Compile(src);
}
/// <summary>
/// Compile the specified src.
/// </summary>
/// <param name="src">Source.</param>
public string Compile(string src, Microsoft.Scripting.SourceCodeKind CodeKind =
Microsoft.Scripting.SourceCodeKind.SingleStatement)
{
if(src == string.Empty)
return string.Empty;
LoadRuntime();
Source = CodeKind == Microsoft.Scripting.SourceCodeKind.SingleStatement ?
Engine.CreateScriptSourceFromString(src, CodeKind) :
Engine.CreateScriptSourceFromFile(src);
ErrorHandle errors = new ErrorHandle();
MemoryStream stream = new MemoryStream();
//Set IO Ouput of execution
Engine.Runtime.IO.SetOutput(stream, new StreamWriter(stream));
Compiled = Source.Compile(errors);
Operation = Engine.CreateOperations();
try {
Compiled.Execute(Scope);
return FormatOutput(ReadFromStream(stream));
} catch(Exception ex) {
return Engine.GetService<ExceptionOperations>().FormatException(ex);
}
}
/// <summary>
/// Formats the output of execution
/// </summary>
/// <returns>The output.</returns>
/// <param name="output">Output.</param>
private string FormatOutput(string output)
{
return string.IsNullOrEmpty(output) ? string.Empty
: string.Join("\n", output.Remove(output.Length-1)
.Split('\n')
.Reverse().ToArray());
}
/// <summary>
/// Reads MemoryStream.
/// </summary>
/// <returns>The from stream.</returns>
/// <param name="ms">Ms.</param>
private string ReadFromStream(MemoryStream ms) {
int length = (int)ms.Length;
Byte[] bytes = new Byte[ms.Length];
ms.Seek(0, SeekOrigin.Begin);
ms.Read(bytes, 0, length);
return Encoding.GetEncoding("utf-8").GetString(bytes, 0, length);
}
/// <summary>
/// Set sys paths
/// </summary>
private void SetLibrary()
{
if(PythonBase.SysPath.Count > 0) {
ICollection<string> SysPath = Engine.GetSearchPaths();
foreach(string path in PythonBase.SysPath)
SysPath.Add(path);
Engine.SetSearchPaths(SysPath);
}
}
/// <summary>
/// Load runtime Assemblies of Unity3D
/// </summary>
private void LoadRuntime()
{
Engine.Runtime.LoadAssembly(typeof(GameObject).Assembly);
}
public void AddRuntime<T>()
{
Engine.Runtime.LoadAssembly(typeof(T).Assembly);
}
public void AddRuntime(Type type)
{
Engine.Runtime.LoadAssembly(type.Assembly);
}
/// <summary>
/// Gets the variable or class
/// </summary>
/// <returns>The variable.</returns>
/// <param name="name">Name.</param>
public object GetVariable(string name)
{
return Operation.Invoke(Scope.GetVariable(name));
}
/// <summary>
/// Calls the method.
/// </summary>
/// <param name="name">Name.</param>
public void InvokeMethod(object nameClass, string Method, params object[] parameters)
{
object output = new object();
if(Operation.TryGetMember(nameClass, Method, out output)) {
object Func = Operation.GetMember(nameClass, Method);
Operation.Invoke(Func, parameters);
}
}
}
I found this code and it looks like a fixed version of the C# version of FileSystemWatcher from Microsoft. However the problem is that I have no idea how to use or run it. Could someone with some expertise please shed some light for me? How do I use this code?
The original source and explanation is here I believe. I've tried to contact the originator but I cannot get a response.
http://fascinatedwithsoftware.com/blog/post/2012/12/30/How-to-Use-FileSystemWatcher-Instead-of-Polling.aspx
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Threading;
namespace Fws.Collections
{
/// <summary>
/// Detects the arrival of files in a directory and makes them available to a client class
/// as an IEnumerable of fully pathed file names. Unlike the .NET FileSystemWatcher, this
/// class yields files that exist when the object is constructed. Also, it is not an IDisposable.
/// </summary>
/// <remarks>
/// <para>
/// If a file arrives during the execution of this class's constructor, it may be reported more than
/// once. Also, some programs write their files in such a way that the underlying FileSystemWatcher
/// will fire a Create event more than once. In those cases, this class will yield the
/// file multiple times.
/// </para><para>
/// Client code must account for these possibilities. It is envisioned that wrapping classes may
/// refine the yielded files by waiting for them to quiesce, filtering out duplicates, etc.
/// </para>
/// <para>
/// This class is thread-safe: more than one thread may enumerate the files presented by a
/// single instance of this class, and each thread will get all the files.
/// </para>
/// </remarks>
public sealed class CreatedFileCollection : IEnumerable<string>
{
#region Fields
readonly string _directory;
readonly string _filePattern;
readonly CancellationToken _cancellationToken;
#endregion
#region Nested Class to Collect Results
/// <summary>
/// A queue of files found within one GetEnumerator call.
/// </summary>
private sealed class CreatedFileQueue : IDisposable
{
readonly ConcurrentQueue<string> _queue = new ConcurrentQueue<string>();
readonly SemaphoreSlim _fileEnqueued = new SemaphoreSlim(0);
/// <summary>
/// Attempt to get a file from the queue.
/// </summary>
/// <param name="fileName">The name of the file, if one is immediately available.</param>
/// <returns>True if got a file; false if not.</returns>
public bool TryDequeue(out string fileName, CancellationToken cancellationToken)
{
fileName = null;
// Avoid the OperationCanceledException if we can.
if (cancellationToken.IsCancellationRequested)
return false;
try
{
_fileEnqueued.Wait(cancellationToken);
return _queue.TryDequeue(out fileName);
}
catch (OperationCanceledException)
{
return false;
}
}
/// <summary>
/// Handles the Created event of the enclosing class's FileSystemWatcher.
/// </summary>
/// <param name="sender">This object.</param>
/// <param name="e">Args for the new file.</param>
public void FileCreated(object sender, FileSystemEventArgs e)
{
_queue.Enqueue(e.FullPath);
_fileEnqueued.Release();
}
public void Dispose()
{
_fileEnqueued.Dispose();
}
}
#endregion
#region Constructor
/// <summary>
/// Constructor.
/// </summary>
/// <param name="cancellationToken">This class will terminate the enumeration of
/// files when and only when the token enters the canceled state.</param>
/// <param name="directory">The directory to watch.</param>
/// <param name="filePattern">A pattern to match in the file name. Example: "*.txt".
/// Null means all files.</param>
/// <remarks>Duplicates may be returned on the queue. See remarks for the class.</remarks>
public CreatedFileCollection(CancellationToken cancellationToken, string directory, string filePattern=null)
{
Contract.Requires(directory != null);
Contract.Requires(cancellationToken != null);
if (!Directory.Exists(directory))
throw new ArgumentException(String.Format("Directory '{0}' does not exist.", directory));
_directory = directory;
_filePattern = filePattern ?? "*";
_cancellationToken = cancellationToken;
}
#endregion
#region Methods
/// <summary>
/// Get an enumerator that will yield files until the CanellationToken is canceled.
/// </summary>
/// <returns>Fully pathed file names.</returns>
/// <remarks>
/// It is possible for a file name to be returned from more than once.
/// </remarks>
public IEnumerator<string> GetEnumerator()
{
if (!_cancellationToken.IsCancellationRequested)
{
using (var watcher = new FileSystemWatcher(_directory, _filePattern))
{
using (var queue = new CreatedFileQueue())
{
// Restrict the NotifyFilter to all that's necessary for Create events.
// This minimizes the likelihood that FileSystemWatcher's buffer will be overwhelmed.
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Created += queue.FileCreated;
watcher.EnableRaisingEvents = true;
// Note that if a file arrives during the following loop, it will be placed on the queue
// twice: once when the Create event is raised, and once by the loop itself.
foreach (var file in Directory.GetFiles(_directory, _filePattern, SearchOption.TopDirectoryOnly))
{
queue.FileCreated(this, new FileSystemEventArgs(WatcherChangeTypes.Created, _directory, Path.GetFileName(file)));
}
if (!_cancellationToken.IsCancellationRequested)
{
string fileName;
while (queue.TryDequeue(out fileName, _cancellationToken))
yield return fileName;
}
}
}
}
}
/// <summary>
/// Required method for IEnumerable.
/// </summary>
/// <returns>The generic enumerator, but as a non-generic version.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
}
Here is an example I knocked up which seems to work.
public static void Main()
{
var watcher = new CreatedFileCollection(CancellationToken.None, "c:\\test");
var enumerator = watcher.GetEnumerator();
Task.Run(() =>
{
//This will block until either a new file is created or the
//passed CancellationToken is cancelled.
while (enumerator.MoveNext())
{
Console.WriteLine("New File - " + enumerator.Current);
}
});
Console.ReadLine();
}
This will print a line for all files that are created while the program is running.
in my main WPF application code i need to run .exe app with command prompt. this action is executed inside backgroundworker i have the following code. the code is running readlines.exe app with command prompt and read the output lines into a string (str).
string str;
ProcessStartInfo proc = new ProcessStartInfo();
proc.WindowStyle = ProcessWindowStyle.Hidden;
proc.UseShellExecute = true;
proc.FileName = #"readlines.exe";
proc.Arguments = #"";
proc.UseShellExecute = false;
proc.RedirectStandardOutput = true;
proc.CreateNoWindow = true;
proc.RedirectStandardInput = true;
Process proc1 = Process.Start(proc);
proc1.StandardInput.WriteLine("");
str = proc1.StandardOutput.ReadToEnd();
i want to ad timeout to the below line so when the timeout will be finised the procces will be canceled (as CTR+C) and "str" will get the output text until this point.
str = proc1.StandardOutput.ReadToEnd();
is it possible?
Although the previous answer has already been accepted here is a maybe more useful, secure and performant solution. Further it does not make use of the ReadLine() method which would block until there has been one line written (which may never occur). It uses an instance of StringBuilder and reads from the stream in specifyable data blocks (default size is 128 characters). Furthermore it supports event based notification of read data.
The usage of the class stays the same.
ProcessOutputReader por = new ProcessOutputReader(proc1);
por.StartReading();
// Do whatever you want here
// (e.g. sleep or whatever)
por.StopReading();
// Now you have everything that has been read in por.Data
However I've added the OnDataRead event which is fired every time new data has been read. You can access the data by using e.g. following code:
...
// Subscribe to the event
por.OnDataRead += OnDataReadEventHandler;
...
The callback method / event handler would look something like this:
private void OnDataReadEventHandler(object sender, ProcessOutputReaderEventArgs e)
{
// e.IntermediateDataStore points to the StringBuilder instance which holds
// all the data that has been received until now.
string completeData = e.IntermediateDataStore.ToString();
// e.NewData points to a string which contains the data that has been received
// since the last triggered event (because the event is triggered on each read).
string newData = e.NewData;
}
The modified ProcessOutputReader class looks like this:
/// <summary>
/// Represents the ProcessOutputReader class.
/// </summary>
public class ProcessOutputReader
{
/// <summary>
/// Represents the instance of the thread arguments class.
/// </summary>
private ProcessOutputReaderWorkerThreadArguments threadArguments;
/// <summary>
/// Initializes a new instance of the <see cref="ProcessOutputReader"/> class.
/// </summary>
/// <param name="process">The process which's output shall be read.</param>
/// <exception cref="System.ArgumentOutOfRangeException">Is thrown if the specified process reference is null.</exception>
public ProcessOutputReader(Process process)
{
if (process == null)
{
throw new ArgumentOutOfRangeException("process", "The parameter \"process\" must not be null");
}
this.Process = process;
this.IntermediateDataStore = new StringBuilder();
this.threadArguments = new ProcessOutputReaderWorkerThreadArguments(this.Process, this.IntermediateDataStore);
}
/// <summary>
/// Is fired whenever data has been read from the process output.
/// </summary>
public event EventHandler<ProcessOutputReaderEventArgs> OnDataRead;
/// <summary>
/// Gets or sets the worker thread.
/// </summary>
private Thread ReaderThread
{
get;
set;
}
/// <summary>
/// Gets or sets the intermediate data store.
/// </summary>
private StringBuilder IntermediateDataStore
{
get;
set;
}
/// <summary>
/// Gets the data collected from the process output.
/// </summary>
public string Data
{
get
{
return this.IntermediateDataStore.ToString();
}
}
/// <summary>
/// Gets the process.
/// </summary>
public Process Process
{
get;
private set;
}
/// <summary>
/// Stars reading from the process output.
/// </summary>
public void StartReading()
{
if (this.ReaderThread != null)
{
if (this.ReaderThread.IsAlive)
{
return;
}
}
this.ReaderThread = new Thread(new ParameterizedThreadStart(ReaderWorker));
this.threadArguments.Exit = false;
this.ReaderThread.Start(this.threadArguments);
}
/// <summary>
/// Stops reading from the process output.
/// </summary>
public void StopReading()
{
if (this.ReaderThread != null)
{
if (this.ReaderThread.IsAlive)
{
this.threadArguments.Exit = true;
this.ReaderThread.Join();
}
}
}
/// <summary>
/// Fires the OnDataRead event.
/// </summary>
/// <param name="newData">The new data that has been read.</param>
protected void FireOnDataRead(string newData)
{
if (this.OnDataRead != null)
{
this.OnDataRead(this, new ProcessOutputReaderEventArgs(this.IntermediateDataStore, newData));
}
}
/// <summary>
/// Represents the worker method.
/// </summary>
/// <param name="data">The thread arguments, must be an instance of the <see cref="ProcessOutputReaderWorkerThreadArguments"/> class.</param>
private void ReaderWorker(object data)
{
ProcessOutputReaderWorkerThreadArguments args;
try
{
args = (ProcessOutputReaderWorkerThreadArguments)data;
}
catch
{
return;
}
try
{
char[] readBuffer = new char[args.ReadBufferSize];
while (!args.Exit)
{
if (args.Process == null)
{
return;
}
if (args.Process.HasExited)
{
return;
}
if (args.Process.StandardOutput.EndOfStream)
{
return;
}
int readBytes = this.Process.StandardOutput.Read(readBuffer, 0, readBuffer.Length);
args.IntermediateDataStore.Append(readBuffer, 0, readBytes);
this.FireOnDataRead(new String(readBuffer, 0, readBytes));
}
}
catch (ThreadAbortException)
{
if (!args.Process.HasExited)
{
args.Process.Kill();
}
}
}
}
In addition you need the ProcessOutputReaderWorkerThreadArguments class which looks like this:
/// <summary>
/// Represents the ProcessOutputReaderWorkerThreadArguments class.
/// </summary>
public class ProcessOutputReaderWorkerThreadArguments
{
/// <summary>
/// Represents the read buffer size,
/// </summary>
private int readBufferSize;
/// <summary>
/// Initializes a new instance of the <see cref="ProcessOutputReaderWorkerThreadArguments"/> class.
/// </summary>
/// <param name="process">The process.</param>
/// <param name="intermediateDataStore">The intermediate data store.</param>
public ProcessOutputReaderWorkerThreadArguments(Process process, StringBuilder intermediateDataStore)
{
this.ReadBufferSize = 128;
this.Exit = false;
this.Process = process;
this.IntermediateDataStore = intermediateDataStore;
}
/// <summary>
/// Gets or sets a value indicating whether the thread shall exit or not.
/// </summary>
public bool Exit
{
get;
set;
}
/// <summary>
/// Gets or sets the read buffer size in bytes.
/// </summary>
/// <exception cref="System.ArgumentOutOfRangeException">Is thrown if the specified value is not greather than 0.</exception>
public int ReadBufferSize
{
get
{
return this.readBufferSize;
}
set
{
if (value <= 0)
{
throw new ArgumentOutOfRangeException("value", "The specified value for \"ReadBufferSize\" must be greater than 0.");
}
this.readBufferSize = value;
}
}
/// <summary>
/// Gets the process.
/// </summary>
public Process Process
{
get;
private set;
}
/// <summary>
/// Gets the intermediate data store.
/// </summary>
public StringBuilder IntermediateDataStore
{
get;
private set;
}
}
And the ProcessOutputReaderEventArgs class which looks like this:
/// <summary>
/// Represents the ProcessOutputReaderEventArgs class.
/// </summary>
public class ProcessOutputReaderEventArgs : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="ProcessOutputReaderEventArgs"/> class.
/// </summary>
/// <param name="intermediateDataStore">The reference to the intermediate data store.</param>
/// <param name="newData">The new data that has been read.</param>
public ProcessOutputReaderEventArgs(StringBuilder intermediateDataStore, string newData)
{
this.IntermediateDataStore = intermediateDataStore;
this.NewData = newData;
}
/// <summary>
/// Gets the reference to the intermediate data store.
/// </summary>
public StringBuilder IntermediateDataStore
{
get;
private set;
}
/// <summary>
/// Gets the new data that has been read.
/// </summary>
public string NewData
{
get;
private set;
}
}
Some example how to achieve this (attention, code not tested and can be improved)
ProcessOutputReader por = new ProcessOutputReader(proc1);
por.StartReading();
// Do whatever you want here
// (e.g. sleep or whatever)
por.StopReading();
// Now you have everything that has been read in por.Lines
The class would look like:
public class ProcessOutputReader
{
public ProcessOutputReader(Process process)
{
this.Process = process;
this.Lines = new List<string>();
}
public List<string> Lines
{
get;
private set;
}
public Process Process
{
get;
private set;
}
private Thread ReaderThread
{
get;
set;
}
public void StartReading()
{
if (this.ReaderThread == null)
{
this.ReaderThread = new Thread(new ThreadStart(ReaderWorker));
}
if (!this.ReaderThread.IsAlive)
{
this.ReaderThread.Start();
}
}
public void StopReading()
{
if (this.ReaderThread != null)
{
if (this.ReaderThread.IsAlive)
{
this.ReaderThread.Abort();
this.ReaderThread.Join();
}
}
}
private void ReaderWorker()
{
try
{
while (!this.Process.HasExited)
{
string data = this.Process.StandardOutput.ReadLine();
this.Lines.Add(data);
}
}
catch (ThreadAbortException)
{
if (!this.Process.HasExited)
{
this.Process.Kill();
}
}
}
}
I found this class on the internet but it didn't have any example usage. I tried reading it and the <events> are confusing me. When I try to initialize an event it stays null even after the irc.DataRead+=new EventHandler<DataReadEventArgs>(irc_DataRead);
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace asynchronous
{
/// <summary>
/// Represents an asynchronous Tcp Client.
/// </summary>
public class Client
{
/// <summary>
/// The default length for the read buffer.
/// </summary>
private const int DefaultClientReadBufferLength = 4096;
/// <summary>
/// The tcp client used for the outgoing connection.
/// </summary>
private readonly TcpClient client;
/// <summary>
/// The port to connect to on the remote server.
/// </summary>
private readonly int port;
/// <summary>
/// A reset event for use if a DNS lookup is required.
/// </summary>
private readonly ManualResetEvent dnsGetHostAddressesResetEvent = null;
/// <summary>
/// The length of the read buffer.
/// </summary>
private readonly int clientReadBufferLength;
/// <summary>
/// The addresses to try connection to.
/// </summary>
private IPAddress[] addresses;
/// <summary>
/// How many times to retry connection.
/// </summary>
private int retries;
/// <summary>
/// Occurs when the client connects to the server.
/// </summary>
public event EventHandler Connected;
/// <summary>
/// Occurs when the client disconnects from the server.
/// </summary>
public event EventHandler Disconnected;
/// <summary>
/// Occurs when data is read by the client.
/// </summary>
public event EventHandler<DataReadEventArgs> DataRead;
/// <summary>
/// Occurs when data is written by the client.
/// </summary>
public event EventHandler<DataWrittenEventArgs> DataWritten;
/// <summary>
/// Occurs when an exception is thrown during connection.
/// </summary>
public event EventHandler<ExceptionEventArgs> ClientConnectException;
/// <summary>
/// Occurs when an exception is thrown while reading data.
/// </summary>
public event EventHandler<ExceptionEventArgs> ClientReadException;
/// <summary>
/// Occurs when an exception is thrown while writing data.
/// </summary>
public event EventHandler<ExceptionEventArgs> ClientWriteException;
/// <summary>
/// Occurs when an exception is thrown while performing the DNS lookup.
/// </summary>
public event EventHandler<ExceptionEventArgs> DnsGetHostAddressesException;
/// <summary>
/// Constructor for a new client object based on a host name or server address string and a port.
/// </summary>
/// <param name="hostNameOrAddress">The host name or address of the server as a string.</param>
/// <param name="port">The port on the server to connect to.</param>
/// <param name="clientReadBufferLength">The clients read buffer length.</param>
public Client(string hostNameOrAddress, int port, int clientReadBufferLength = DefaultClientReadBufferLength)
: this(port, clientReadBufferLength)
{
this.dnsGetHostAddressesResetEvent = new ManualResetEvent(false);
Dns.BeginGetHostAddresses(hostNameOrAddress, this.DnsGetHostAddressesCallback, null);
}
/// <summary>
/// Constructor for a new client object based on a number of IP Addresses and a port.
/// </summary>
/// <param name="addresses">The IP Addresses to try connecting to.</param>
/// <param name="port">The port on the server to connect to.</param>
/// <param name="clientReadBufferLength">The clients read buffer length.</param>
public Client(IPAddress[] addresses, int port, int clientReadBufferLength = DefaultClientReadBufferLength)
: this(port, clientReadBufferLength)
{
this.addresses = addresses;
}
/// <summary>
/// Constructor for a new client object based on a single IP Address and a port.
/// </summary>
/// <param name="address">The IP Address to try connecting to.</param>
/// <param name="port">The port on the server to connect to.</param>
/// <param name="clientReadBufferLength">The clients read buffer length.</param>
public Client(IPAddress address, int port, int clientReadBufferLength = DefaultClientReadBufferLength)
: this(new[] { address }, port, clientReadBufferLength)
{
}
/// <summary>
/// Private constructor for a new client object.
/// </summary>
/// <param name="port">The port on the server to connect to.</param>
/// <param name="clientReadBufferLength">The clients read buffer length.</param>
private Client(int port, int clientReadBufferLength)
{
this.client = new TcpClient();
this.port = port;
this.clientReadBufferLength = clientReadBufferLength;
}
/// <summary>
/// Starts an asynchronous connection to the remote server.
/// </summary>
public void Connect()
{
if (this.dnsGetHostAddressesResetEvent != null)
this.dnsGetHostAddressesResetEvent.WaitOne();
this.retries = 0;
this.client.BeginConnect(this.addresses, this.port, this.ClientConnectCallback, null);
}
/// <summary>
/// Writes a string to the server using a given encoding.
/// </summary>
/// <param name="value">The string to write.</param>
/// <param name="encoding">The encoding to use.</param>
/// <returns>A Guid that can be used to match the data written to the confirmation event.</returns>
public Guid Write(string value, Encoding encoding)
{
byte[] buffer = encoding.GetBytes(value);
return this.Write(buffer);
}
/// <summary>
/// Writes a byte array to the server.
/// </summary>
/// <param name="buffer">The byte array to write.</param>
/// <returns>A Guid that can be used to match the data written to the confirmation event.</returns>
public Guid Write(byte[] buffer)
{
Guid guid = Guid.NewGuid();
NetworkStream networkStream = this.client.GetStream();
networkStream.BeginWrite(buffer, 0, buffer.Length, this.ClientWriteCallback, guid);
return guid;
}
/// <summary>
/// Callback from the asynchronous DNS lookup.
/// </summary>
/// <param name="asyncResult">The result of the async operation.</param>
private void DnsGetHostAddressesCallback(IAsyncResult asyncResult)
{
try
{
this.addresses = Dns.EndGetHostAddresses(asyncResult);
this.dnsGetHostAddressesResetEvent.Set();
}
catch (Exception ex)
{
if (this.DnsGetHostAddressesException != null)
this.DnsGetHostAddressesException(this, new ExceptionEventArgs(ex));
}
}
/// <summary>
/// Callback from the asynchronous Connect method.
/// </summary>
/// <param name="asyncResult">The result of the async operation.</param>
private void ClientConnectCallback(IAsyncResult asyncResult)
{
try
{
this.client.EndConnect(asyncResult);
if (this.Connected != null)
this.Connected(this, new EventArgs());
}
catch (Exception ex)
{
retries++;
if (retries < 3)
{
this.client.BeginConnect(this.addresses, this.port, this.ClientConnectCallback, null);
}
else
{
if (this.ClientConnectException != null)
this.ClientConnectException(this, new ExceptionEventArgs(ex));
}
return;
}
try
{
NetworkStream networkStream = this.client.GetStream();
byte[] buffer = new byte[this.clientReadBufferLength];
networkStream.BeginRead(buffer, 0, buffer.Length, this.ClientReadCallback, buffer);
}
catch (Exception ex)
{
if (this.ClientReadException != null)
this.ClientReadException(this, new ExceptionEventArgs(ex));
}
}
/// <summary>
/// Callback from the asynchronous Read method.
/// </summary>
/// <param name="asyncResult">The result of the async operation.</param>
private void ClientReadCallback(IAsyncResult asyncResult)
{
try
{
NetworkStream networkStream = this.client.GetStream();
int read = networkStream.EndRead(asyncResult);
if (read == 0)
{
if (this.Disconnected != null)
this.Disconnected(this, new EventArgs());
}
byte[] buffer = asyncResult.AsyncState as byte[];
if (buffer != null)
{
byte[] data = new byte[read];
Buffer.BlockCopy(buffer, 0, data, 0, read);
networkStream.BeginRead(buffer, 0, buffer.Length, this.ClientReadCallback, buffer);
if (this.DataRead != null)
this.DataRead(this, new DataReadEventArgs(data));
}
}
catch (Exception ex)
{
if (this.ClientReadException != null)
this.ClientReadException(this, new ExceptionEventArgs(ex));
}
}
/// <summary>
/// Callback from the asynchronous write callback.
/// </summary>
/// <param name="asyncResult">The result of the async operation.</param>
private void ClientWriteCallback(IAsyncResult asyncResult)
{
try
{
NetworkStream networkStream = this.client.GetStream();
networkStream.EndWrite(asyncResult);
Guid guid = (Guid)asyncResult.AsyncState;
if (this.DataWritten != null)
this.DataWritten(this, new DataWrittenEventArgs(guid));
}
catch (Exception ex)
{
if (this.ClientWriteException != null)
this.ClientWriteException(this, new ExceptionEventArgs(ex));
}
}
}
/// <summary>
/// Provides data for an exception occuring event.
/// </summary>
public class ExceptionEventArgs : EventArgs
{
/// <summary>
/// Constructor for a new Exception Event Args object.
/// </summary>
/// <param name="ex">The exception that was thrown.</param>
public ExceptionEventArgs(Exception ex)
{
this.Exception = ex;
}
public Exception Exception { get; private set; }
}
/// <summary>
/// Provides data for a data read event.
/// </summary>
public class DataReadEventArgs : EventArgs
{
/// <summary>
/// Constructor for a new Data Read Event Args object.
/// </summary>
/// <param name="data">The data that was read from the remote host.</param>
public DataReadEventArgs(byte[] data)
{
this.Data = data;
}
/// <summary>
/// Gets the data that has been read.
/// </summary>
public byte[] Data { get; private set; }
}
/// <summary>
/// Provides data for a data write event.
/// </summary>
public class DataWrittenEventArgs : EventArgs
{
/// <summary>
/// Constructor for a Data Written Event Args object.
/// </summary>
/// <param name="guid">The guid of the data written.</param>
public DataWrittenEventArgs(Guid guid)
{
this.Guid = guid;
}
/// <summary>
/// Gets the Guid used to match the data written to the confirmation event.
/// </summary>
public Guid Guid { get; private set; }
}
}
This is what I've tried but I don't get it. I'm new to c#:
using System;
using System.Text;
using System.Threading;
namespace asynchronous
{
class Program
{
private static EventHandler connection;
private static EventHandler<DataReadEventArgs> irc_DataRead;
static void Main(string[] args)
{
var irc = new Client("irc.rizon.net", 6667);
Console.WriteLine("Connecting...");
irc.Connect();
Thread.Sleep(2000);
irc.Write("Test", Encoding.UTF8);
irc.DataRead+=new EventHandler<DataReadEventArgs>(irc_DataRead);
Console.WriteLine(irc_DataRead);
Console.WriteLine("Connected.");
Console.ReadLine();
}
}
}
Could someone please help me setup that class to connect to IRC and read and write text?
Here you are hooking up a null instance of an event handler into an event. You need to hookup an actual method / lambda in order for this to work. Try the following
static void OnDataRead(object sender, DataReadEventArgs e) {
// Data reads call this method
}
static void Main(string[] args) {
...
irc.DataRead += OnDataRead;
...
}
I just can't make out if the entity context is disposed in the usage flow when used in a using statement in a web application or a console application.
Thanks!
using System;
using System.Web;
namespace Foo.Model
{
public partial class FooEntities : ObjectContext
{
private const string CurrentContextKey = "FooEntities.Current";
[ThreadStatic]
private static FooEntities _currentOnThreadStatic;
private FooEntities _previousContext;
/// <summary>
/// Gets the current <see cref="FooEntities"/> instance, if an instance can be shared in the current context.
/// </summary>
/// <remarks>
/// The current context is stored in the HTTP context, if it is available (otherwise it is stored in a thread-static instance).
/// Multiple contexts can be stacked.
/// </remarks>
public static FooEntities Current
{
get
{
if (HttpContext.Current != null)
{
return HttpContext.Current.Items[CurrentContextKey] as FooEntities;
}
else
{
return _currentOnThreadStatic;
}
}
private set
{
if (HttpContext.Current != null)
{
HttpContext.Current.Items[CurrentContextKey] = value;
}
else
{
_currentOnThreadStatic = value;
}
}
}
/// <summary>
/// Returns a repository instance bound to this object context.
/// </summary>
/// <typeparam name="TRepository">The type of repository to instantiate.</typeparam>
/// <returns>The repository instance.</returns>
public TRepository GetRepository<TRepository>()
where TRepository: BaseRepository
{
return (TRepository) Activator.CreateInstance(typeof(TRepository), this);
}
/// <summary>
/// Ensures that an ambient context is available through <see cref="Current"/>, throwing an exception otherwise.
/// </summary>
/// <exception type="InvalidOperationException)">
/// Thrown if <see cref="Current"/> is null.
/// </exception>
public static void EnsureContext()
{
if (Current == null)
{
throw new InvalidOperationException("An ambient FooEntities context is expected.");
}
}
/// <summary>
/// Releases the context instance.
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
Current = _previousContext;
base.Dispose(disposing);
}
/// <summary>
/// Is called by all constructors.
/// </summary>
partial void OnContextCreated()
{
_previousContext = Current;
Current = this;
}
}
}
It is an odd design. As #Joel C points out in his comment you should regard the object context as a shortlived object that you create when you need it and release right afterwards.
But I see no reason that this would leak memory. You are only dealing with managed resources and you are using the same key all the time to the HttpContext so you won't create new objects all over.