C# WaitHandle.WaitAll() is always waiting - c#

Following is my code , the wait all method is always waiting .
class Program
{
static StreamWriter _fileStream;
static void Main(string[] args)
{
_fileStream = File.CreateText(#"C:\Praveen\HelloThread.txt");
List<ManualResetEvent> meList = new List<ManualResetEvent>();
ManualResetEvent currentEvent = new ManualResetEvent(true);
ManualResetEvent nextEvent = new ManualResetEvent(false);
meList.Add(currentEvent);
int length = 10;
Data data = null;
Console.WriteLine("Writing started...");
for (int i = 0; i < length; i++)
{
data = new Data { CurrentEvent = currentEvent, Number = i, NextEvent = nextEvent };
ThreadPool.QueueUserWorkItem(PrintMsg, data);
meList.Add(nextEvent);
currentEvent = nextEvent;
nextEvent = nextEvent = new ManualResetEvent(false);
}
CloseAll(meList);
Console.ReadLine();
}
private static void CloseAll(List<ManualResetEvent> meList)
{
Console.WriteLine("Requested to close all...");
while (WaitHandle.WaitAll(meList.ToArray()))
{
}
Console.WriteLine("Done with the writing...");
}
private static void PrintMsg(object state)
{
Data data = state as Data;
data.CurrentEvent.WaitOne();
string msg = "Hello times...";
for (int j = 0; j < 5; j++)
{
_fileStream.WriteLine(msg + data.Number);
Console.WriteLine(msg + data.Number);
}
data.NextEvent.Set();
}
}
public class Data
{
public ManualResetEvent CurrentEvent { get; set; }
public ManualResetEvent NextEvent { get; set; }
public int Number { get; set; }
}
What's going on , why it's always waiting , any idea ?

You have an infinite loop in your CloseAll method. WaitAll returns true when all events are signaled. You do not need the empty while loop, just add the line:
WaitHandle.WaitAll(meList.ToArray());

Related

SortedDictionary key Object duplicate Problem

I have a SortedDictionary with Object as key, which implements the IComparable interface,
but the result is not correct.
here is the code
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace TestApp {
public class Program
{
public class UserPrice : IComparable<UserPrice>
{
public string Wxid { get; set; }
public int Num { get; set; }
public int Price{ get; set; }
public DateTime PriceTime { get; set; }
public int CompareTo(UserPrice other)
{
if (Wxid == other.Wxid)
{
return 0;
}
if (Price != other.Price)
{
return other.Price.CompareTo(Price);
}
return PriceTime.CompareTo(other.PriceTime);
}
public override string ToString()
{
return String.Format("wxid={0}, num={1}, price={2}, priceTime={3}", Wxid, Num, Price, PriceTime);
}
}
private SortedDictionary<UserPrice, int> sortedPriceDict = new SortedDictionary<UserPrice, int>();
private BlockingCollection<UserPrice> chan = new BlockingCollection<UserPrice>();
private void MockMessage()
{
sortedPriceDict = new SortedDictionary<UserPrice, int>();
var task = Task.Run((Action)MockRecvMsg);
for (var i = 0; i < 10; i++)
{
var j = i;
Task.Run(() => MockSendMsg(j));
}
task.Wait();
}
private void MockRecvMsg()
{
while (true)
{
var p = chan.Take();
sortedPriceDict[p] = 1;
//Console.WriteLine(sortedPriceDict.Count + "," + p);
if(sortedPriceDict.Count > 10)
{
break;
}
}
foreach(var up in sortedPriceDict){
Console.WriteLine(up);
}
}
private async void MockSendMsg(int i)
{
var wxId = String.Format("user_{0}", i);
var rand = new Random();
var basePrice = 320;
while(true)
{
var up = new UserPrice();
up.Wxid = wxId;
up.Price = rand.Next(basePrice, basePrice + 100) * 100;
up.Num = rand.Next(1, 10);
up.PriceTime = DateTime.Now;
//Console.WriteLine(up);
chan.Add(up);
await Task.Delay(rand.Next(1, 5) * 1000);
}
}
public static void Main()
{
var main = new Program();
main.MockMessage();
}
}
}
I want to sort by [Price desc, PriceTime asc], user price with the same Wxid should by unique in the SortedDictionary, I start 10 Tasks to produce messages from 10 users, and 1 consumer to save the messages into the sortedDictionary, but after run for a while, the program will stop, because the dictionary's count is > 10, so what's wrong with my code ? Do I miss anything?

Background work completed never fired

After background process DoWork() the control is exit from the block but it never fire a RunWorkerCompleted() and one more thing is isBusy is still true
Please help me
Dispatcher.CurrentDispatcher.Invoke(new Action(() =>
{
sendFile.Send();
}));
This is my FileReadWrite.cs file
Whenever I used this file in xaml class file it worked but there I am using Dispatcher in DispatcherObject class from WindowBase.dll but in another .cs file I can't use that DispatcherObject class that's why I am using Dispatcher.CurrentDispatcher.Invoke()
public class FileReadWrite
{
public int SourceId;
public int DestinationId;
public string FileName;
public WebSocket WebSocket;
public int SplitSize;
public int ReferenceId;
BinaryWriter _binaryWriter;
public int _totalsequence = 0;
public int progvalue;
public static double totallength;
public static double calculate, sendlen;
public static int post;
public double calc, count, len, sentsize;
public static int FileSendCount = 0;
public static List<byte[]> FileList = new List<byte[]>();
public BackgroundWorker _worker = new BackgroundWorker();
public FileReadWrite()
{
_worker.DoWork += _worker_DoWork;
_worker.RunWorkerCompleted += _worker_RunWorkerCompleted;
}
void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
FileCloseMessage fileclosemsg = new FileCloseMessage();
fileclosemsg.Source = SourceId;
fileclosemsg.Destination = DestinationId;
fileclosemsg.Date = DateTime.Now;
fileclosemsg.Sequenceno = 0;
fileclosemsg.totalsequence = _totalsequence;
byte[] bytess = fileclosemsg.GetBytes();
FileList.Add(bytess);
}
void _worker_DoWork(object sender, DoWorkEventArgs e)
{
using (BinaryReader b = new BinaryReader(File.Open(FileName, FileMode.Open)))
{
int pos = 0;
int length = (int)b.BaseStream.Length;
totallength = Convert.ToDouble(length);
byte[] bytes = new byte[SplitSize];
while (pos < length)
{
if (pos + SplitSize > length)
{
bytes = new byte[length - pos];
}
len = Convert.ToDouble(length);
bytes = b.ReadBytes(bytes.Length);
FileContentMesssage fileContentMesssage = new FileContentMesssage();
fileContentMesssage.Content = bytes;
fileContentMesssage.ReferenceId = ReferenceId;
pos += SplitSize;
fileContentMesssage.SequenceNo = pos / SplitSize;
_totalsequence++;
byte[] filebytes = fileContentMesssage.GetBytes();
FileList.Add(filebytes);
}
}
}
public async void Send()
{
_worker.RunWorkerAsync();
}
public void FileReceive(byte[] bytes)
{
try
{
if (_binaryWriter != null)
_binaryWriter.Write(bytes);
}
catch (Exception ex)
{
}
}
public string FileCreate()
{
string path = AppDomain.CurrentDomain.BaseDirectory;
string filename = Path.GetFileName(FileName);
string fullfilename = string.Format("{0}{1}", path, filename);
_binaryWriter = new BinaryWriter(File.Open(fullfilename, FileMode.Create));
return (fullfilename);
}
public void FileClose()
{
_binaryWriter.Close();
}
public byte[] FileSend()
{
byte[] bytess = FileList[FileSendCount];
FileSendCount++;
return (bytess);
}
public void FileClosed()
{
FileSendCount = 0;
FileList.Clear();
post = 0;
sendlen = 0;
calculate = 0;
totallength = 0;
_totalsequence = 0;
}
}

ObservableCollection binary serialization and transfer over the network

There is a small problem ka. there is a class
public class PLayer
{
public String Name{get;set;}
public TimeSpan Tax { get; set; }
}
The main form
public partial class MainWindow : Window
{
public ObservableCollection<PLayer> PlayersInGame { get; set; }
public ObservableCollection<PLayer> PlayersInGame2 { get; set; }
public ObservableCollection<PLayer> PlayersOnBench { get; set; }
public MainWindow()
{
PlayersInGame = new ObservableCollection<PLayer>();
PlayersInGame2 = new ObservableCollection<PLayer>();
PlayersOnBench = new ObservableCollection<PLayer>();
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 10; i++)
{
String vName = "Игрок" + i.ToString();
PlayersInGame.Add(new PLayer { Name = vName, Tax = new TimeSpan(0) });
}
for (int i = 10; i < 20; i++)
{
String vName = "Игрок" + i.ToString();
PlayersInGame2.Add(new PLayer { Name = vName, Tax = new TimeSpan(0) });
}
Game.Items.Refresh();
}
private void Button2_Click(object sender, RoutedEventArgs e)
{
if (Game.SelectedIndex > -1)
{
var temp = PlayersInGame[Game.SelectedIndex];
//PlayersInGame.RemoveAt(Game.SelectedIndex);
temp.Tax = new TimeSpan(0, 0, 5);
PlayersOnBench.Add(temp);
Game.Items.Refresh();
Bench.Items.Refresh();
}
if (Game2.SelectedIndex > -1)
{
var temp = PlayersInGame2[Game2.SelectedIndex];
//PlayersInGame2.RemoveAt(Game2.SelectedIndex);
temp.Tax = new TimeSpan(0, 0, 5);
PlayersOnBench.Add(temp);
Game2.Items.Refresh();
Bench.Items.Refresh();
}
}
private void timer_Tick(object sender, EventArgs e)
{
foreach (var x in PlayersOnBench)
{
x.Tax -= new TimeSpan(0, 0, 1);
}
List<int> Temp = new List<int>();
for (var i = 0; i < PlayersOnBench.Count; i++)
{
if (PlayersOnBench[i].Tax == TimeSpan.Zero)
{
Temp.Add(i);
}
}
for (int i = Temp.Count - 1; i >= 0; i--)
{
var s = PlayersOnBench[i];
PlayersOnBench.RemoveAt(Temp[i]);
//PlayersInGame.Add(s);
//Game.Items.Refresh();
}
Bench.Items.Refresh();
}
}
On the main form when you click on the button "Button2_Click" line is added to the ListView "Bench" with the addition of a timer. in the treatment of "timer_Tick" The timer is counting all the lines added to the "Bench". Contact ossushestvlyaetsya a Binding. My question is knowing binary serialization, how to transfer the contents of ListView "Bench" to the server to display in a ListView or ListBox. The binary serialization of the project has been in use for sending text fields.
Your question is kind of unclear on what you trying to achieve. In general, if you using binary serialization, it will convert your objects into byte array, you need to de-serialize inorder to get your object back. Below is a sample
BinaryFormatter m_formatter;
Byte[] m_stateData;
List<T> cloned_objList;
public binaryserializer(List<T> PlayersOnBench)
{
if ((!Object.ReferenceEquals(listToClone, null)) && (typeof(T).IsSerializable))
{
m_formatter = new BinaryFormatter();
using (MemoryStream stream = new MemoryStream())
{
try
{
m_formatter.Serialize(stream, PlayersOnBench);
}
catch { }
stream.Seek(0, SeekOrigin.Begin);
m_stateData = stream.ToArray();
}
}
}
public List<T> BenchStates
{
get
{
using (MemoryStream stream = new MemoryStream(m_stateData))
{
try
{
cloned_objList = (List<T>)m_formatter.Deserialize(stream);
}
catch (Exception) { }
}
return cloned_objList;
}
}

Asynchronous socket + waitone()

Let's start with some code:
class InternetConnector
{
private struct ConnectionData
{
public Action<Socket> SuccessHandler { get; set; }
public ClientStateObject clientObj { get; set; }
public Action<Exception> ErrorHandler { get; set; }
public Socket Socket { get; set; }
}
public static ManualResetEvent processingDone = new ManualResetEvent( false );
public static ConcurrentQueue<string> messages = new ConcurrentQueue<string>();
public bool ReceiveMessage(Action<Socket> successHandler, Action<Exception> errorHandler)
{
ClientStateObject obj = new ClientStateObject();
obj.server = client;
var connectionData = new ConnectionData
{
ErrorHandler = errorHandler,
SuccessHandler = successHandler,
Socket = client,
clientObj = obj
};
if (Connected)
{
client.BeginReceive(connectionData.clientObj.buffer, 0, ClientStateObject.bufSize, 0, new AsyncCallback(ReceiveCallback), connectionData);
receive = true;
receiveDone.WaitOne();
}
return receive;
}
private static void ReceiveCallback(IAsyncResult ar)
{
ConnectionData connectionData = new ConnectionData();
bool complete = false;
try
{
connectionData = (ConnectionData)ar.AsyncState;
Socket client = connectionData.Socket;
int num = client.EndReceive(ar);
{
connectionData.clientObj.stringBuffer.Append(Encoding.ASCII.GetString(connectionData.clientObj.buffer, 0, num));
string response = connectionData.clientObj.stringBuffer.ToString();
string[] msgs = response.Split('&');
for (int i = 0; i < msgs.Count(); i++)
{
string sts = msgs[i];
messages.Enqueue(sts + "&" );
}
receiveDone.Set();
if (connectionData.SuccessHandler != null)
{
connectionData.SuccessHandler(client);
processingDone.WaitOne();
client.BeginReceive(connectionData.clientObj.buffer, 0, ClientStateObject.bufSize, 0, new AsyncCallback(ReceiveCallback), connectionData);
}
}
}
catch (Exception e)
{
if (connectionData.ErrorHandler != null)
connectionData.ErrorHandler(e);
}
}
public partial class Form1 : Form
{
private InternetConnector client = new InternetConnector();
private bool isRunning = false;
private void AsyncSuccessHandler(Socket socket)
{
if (InvokeRequired)
{
BeginInvoke(new Action( () => AsyncSuccessHandler( socket ) ));
return;
}
if (InternetConnector.messages.Count() == 0)
{
status.Text = "Signals Receiver: Connected";
status.ForeColor = Color.Green;
isRunning = true;
client.ReceiveMessage(AsyncSuccessHandler, AsyncErrorHandler);
}
else
{
GUIChangeOnConnection();
InternetConnector.processingDone.Set();
}
}
private void GUIChangeOnConnection()
{
for( int i = 0; i < InternetConnector.messages.Count; i++ )
{
string message;
InternetConnector.messages.TryDequeue( out message );
// process the message
}
}
}
Now the problem.
Everything works fine. Reading from the socket is happening. However the call processingDone.WaitOne(); which should block the callback indefinitely until the call to processingDone.Set(); returns too early.
I verified it by setting the breakpoint at the end of the GUIChangeOnConnection(); - function closing bracket line. It hits the breakpoint and looking at the InternetConnector.messages I see that the queue is not empty, which means that the for loop did not finish.
And the second time this breakpoint is hit the number of messages in the queue is sky-rocketing.
What am I doing wrong? Or maybe my design is incorrect?
Thank you.

C# multi-thread ping

I'm working on a network monitoring application, that pings a (not known) number of hosts. So far I have the code below. I've made a class PingHost with a function zping and I called it with the help of a timer once every 2 seconds to let the 2 pings to finish, even if one of them gets TimedOut. But I think a better solution is to generate a new thread for every ping, so that the ping of every host would be independent.
Can anyone give me a hint how to do this?
namespace pinguin
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
PingHost caca = new PingHost();
PingHost caca1 = new PingHost();
this.label1.Text = caca.zping("89.115.14.160");
this.label2.Text = caca1.zping("89.115.14.129");
}
}
public class PingHost
{
public string zping(string dest)
{
Application.DoEvents();
Ping sender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 50;
int failed = 0;
int pingAmount = 5;
string stat = "";
PingReply reply = sender.Send(dest, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
stat = "ok";
}
else
{
stat = "not ok!";
}
return stat;
}
}
}
If you use .NET 4 you can use Parallel.Invoke.
You could handle the Ping.PingCompleted event:
ping.PingCompleted += new PingCompletedEventHandler(ping_PingCompleted);
then use:
ping.SendAsync()
side note: Choose more suitable names for your classes and routines. PingHost is more suitable as a routine name
Once I wrote such a solution (it constantly pings about 300 machines):
public class ManyAdressPing {
private readonly bool bAutoStarted;
private readonly CancellationTokenSource cancel = new CancellationTokenSource();
public ConcurrentDictionary<IPAddress, OneAddressPing> pingi = new ConcurrentDictionary<IPAddress, OneAddressPing>();
public ManyAdressPing(bool AutoStarted = true) {
bAutoStarted = AutoStarted;
}
public int CountPings => pingi.Count;
public void AddPingAddress(IPAddress addr, int msTimeOut = 3000, int BetweenPing = 3000) {
var oap = new OneAddressPing(addr, cancel.Token, msTimeOut, BetweenPing);
if (bAutoStarted) oap.Start();
pingi.TryAdd(oap.ipAddress, oap);
}
public void RemovePingAddress(IPAddress addr) {
if (pingi.TryRemove(addr, out var p)) p.Stop();
}
public void Stop() {
cancel.Cancel();
foreach (var pair in pingi) pair.Value.Stop();
}
public PingReply GetReply(IPAddress addr) {
if (pingi.ContainsKey(addr)) return pingi[addr].GetReply();
return null;
}
public Tuple<long, long> GetSuccessOperation(IPAddress addr) {
if (pingi.ContainsKey(addr)) return pingi[addr].GetSuccessOperation();
return null;
}
public PingReply[] GetReply() {
PingReply[] ret = pingi.Values.Select(x=>x.GetReply()).ToArray();
return ret;
}
public PingInfo GetPingInfo(IPAddress addr) {
if (pingi.ContainsKey(addr)) {
var ret = new PingInfo();
var p = pingi[addr];
ret.reply = p.GetReply();
ret.SuccessPing = p._SuccessReply;
ret.FailPing = p._FailReply;
ret.LastSuccessPing = p.LastSuccessfullPing;
return ret;
}
return null;
}
public bool IsPinged(IPAddress addr) {
if (pingi.ContainsKey(addr)) return true;
return false;
}
public IPAddress[] GetAddressesPing() {
return pingi.Keys.ToArray();
}
}
public class PingInfo {
public PingReply reply;
public long SuccessPing = 0;
public long FailPing = 0;
public DateTime LastSuccessPing;
public override string ToString() {
return $"Sping: {SuccessPing} last={LastSuccessPing}, Fping:{FailPing}, reply:{reply}";
}
}
public class OneAddressPing {
public static byte[] bu = {
0
};
public long _FailReply;
public long _SuccessReply;
private bool bStop = false;
private readonly CancellationToken cancellationToken;
public DateTime LastSuccessfullPing = DateTime.MinValue;
public int mSecBetweenPing = 3000;
public Ping ping;
public PingOptions popt;
private Task pTask;
// Here is a self-written LIFO stack
public LightQueue<PingReply> replys = new LightQueue<PingReply>(10);
private readonly AutoResetEvent reset = new AutoResetEvent(false);
private Logger log = null;
private Task pinging = null;
public OneAddressPing(IPAddress addr, CancellationToken ct, int timeOut = 3000, int BetweenPing = 3000, Logger _log =null) {
ipAddress = addr;
popt = new PingOptions();
popt.DontFragment = false;
cancellationToken = ct;
mSecTimeOut = timeOut;
mSecBetweenPing = BetweenPing;
log = _log;
}
public int mSecTimeOut { get; set; } = 3000;
public IPAddress ipAddress { get; set; }
public int CountPings => replys.Length;
private void SetReply(PingReply rep) {
if (rep == null) return;
replys.Put(rep);
if (rep.Status == IPStatus.Success) {
Interlocked.Increment(ref _SuccessReply);
LastSuccessfullPing = DateTime.Now;
} else {
Interlocked.Increment(ref _FailReply);
}
}
public async Task Start() {
if (pTask == null || pTask.Status != TaskStatus.Running) {
ping = new Ping();
Task.Factory.StartNew(PingCircle, TaskCreationOptions.RunContinuationsAsynchronously | TaskCreationOptions.LongRunning); pTask = Task.Run(PingCircle, cancellationToken);
}
}
public void Stop() {
if (pTask.Status == TaskStatus.Running) {
bStop = true;
try {
pTask.Wait(mSecTimeOut, cancellationToken);
} catch (Exception ex) {
log.ErrorSource($"Error ping stop: {ex.Message}");
}
}
}
private async Task PingCircle() {
while (cancellationToken.IsCancellationRequested == false && !bStop) {
try {
try {
PingReply rep = await ping.SendPingAsync(ipAddress, mSecTimeOut, bu,popt);
if (rep != null) SetReply(rep);
} catch (PingException p) {
// ignore ping error
Debug.WriteLine($"error: {p}");
} catch (Exception ee) {
log?.ErrorSource(ee);
Debug.WriteLine($"error: {ee}");
}
await Task.Delay(mSecBetweenPing, cancellationToken);
} catch (Exception ee) {
log?.ErrorSource(ee);
}
}
}
public PingReply GetReply() {
if (replys.IsEmpty) return null;
return replys.PeekLast(0);
}
public Tuple<long, long> GetSuccessOperation() {
return new Tuple<long, long>(_SuccessReply, _FailReply);
}
public bool LongPingSuccess() {
int ret = 0;
for (int i = 0; i < 5; i++) {
var r = replys.PeekLast(i);
if (r.Status == IPStatus.Success) ret++;
}
if (ret > 2) return true;
return false;
}
}

Categories

Resources