copy paste the following code in new C# console app.
class Program
{
static void Main(string[] args)
{
var enumerator = new QueuedEnumerator<long>();
var listenerWaitHandle = Listener(enumerator);
Publisher(enumerator);
listenerWaitHandle.WaitOne();
}
private static AutoResetEvent Listener(IEnumerator<long> items)
{
var #event = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem((o) =>
{
while (items.MoveNext())
{
Console.WriteLine("Received : " + items.Current);
Thread.Sleep(2 * 1000);
}
(o as AutoResetEvent).Set();
}, #event);
return #event;
}
private static void Publisher(QueuedEnumerator<long> enumerator)
{
for (int i = 0; i < 10; i++)
{
enumerator.Set(i);
Console.WriteLine("Sended : " + i);
Thread.Sleep(1 * 1000);
}
enumerator.Finish();
}
class QueuedEnumerator<T> : IEnumerator<T>
{
private Queue _internal = Queue.Synchronized(new Queue());
private T _current;
private bool _finished;
private AutoResetEvent _setted = new AutoResetEvent(false);
public void Finish()
{
_finished = true;
_setted.Set();
}
public void Set(T item)
{
if (_internal.Count > 3)
{
Console.WriteLine("I'm full, give the listener some slack !");
Thread.Sleep(3 * 1000);
Set(item);
}
else
{
_internal.Enqueue(item);
_setted.Set();
}
}
public T Current
{
get { return _current; }
}
public void Dispose()
{
}
object System.Collections.IEnumerator.Current
{
get { return _current; }
}
public bool MoveNext()
{
if (_finished && _internal.Count == 0)
return false;
else if (_internal.Count > 0)
{
_current = (T)_internal.Dequeue();
return true;
}
else
{
_setted.WaitOne();
return MoveNext();
}
}
public void Reset()
{
}
}
}
2 threads (A,B)
A thread can provide one instance at a time and calls the Set method
B thread wants to receive a sequence of instances (provided by thread A)
So literally transforming an Add(item), Add(item), .. to a IEnumerable between different threads
Other solutions also welcome of course!
Sure - this code might not be the best way to do it, but here was my initial stab at it:
Subject<Item> toAddObservable;
ListObservable<Item> buffer;
void Init()
{
// Subjects are an IObservable we can trigger by-hand, they're the
// mutable variables of Rx
toAddObservable = new Subject(Scheduler.TaskPool);
// ListObservable will hold all our items until someone asks for them
// It will yield exactly *one* item, but only when toAddObservable
// is completed.
buffer = new ListObservable<Item>(toAddObservable);
}
void Add(Item to_add)
{
lock (this) {
// Subjects themselves are thread-safe, but we still need the lock
// to protect against the reset in FetchResults
ToAddOnAnotherThread.OnNext(to_add);
}
}
IEnumerable<Item> FetchResults()
{
IEnumerable<Item> ret = null;
buffer.Subscribe(x => ret = x);
lock (this) {
toAddObservable.OnCompleted();
Init(); // Recreate everything
}
return ret;
}
Related
I have a static class A which has a public static ConcurrentQueue.
This class has a method which calls a method of another static class B.
In this method of static class B, a worker thread is started which polls for items in the static ConcurrentQueue of class A. If found, it dequeues the item and processes it.
The same method in class B also starts another thread which checks if the queue of class A is being constantly filled. If the filling occasionally is somehow stuck, a call to a static method in class A is made which resets and restarts the process.
And here comes the problem: When I restart the filling, items are inserted again into the static queue of static class A. But my thread in static class B which checks for items in the queue does not find any items anymore.
So my idea is that in class B I somehow lost the reference to the original static queue of class A. I think I oversee here some principles of static classes, but can not figure out what exactly.
EDIT: Here are some more details.
Main:
public static void Main(string[] args)
{
B.Initialize(8);
A.StartDataStream();
Console.ReadKey();
}
Class A:
class A
{
private static ACOMObject MyCOMObjekt;
public static ConcurrentQueue<PriceItem> Prices = new ConcurrentQueue<PriceItem>();
public static void StartDataStream()
{
DataStream myDataStream = GetDataStream();
FillStream(myDataStream);
B.StartHeartbeatCheck();
Console.WriteLine("Press Key to Exit Stream Call.");
Console.ReadKey();
GC.KeepAlive(myDataStream);
GC.KeepAlive(MyCOMObjekt);
}
private static DataStream GetDataStream()
{
if (MyCOMObjekt== null)
{
MyCOMObjekt= new ACOMObject ();
}
return (DataStream) MyCOMObjekt.DataStream;
}
private static void FillStream(DataStream myDataStream)
{
foreach (var symbol in Symbols.SymbolList)
{
myDataStream.Add(symbolNr, 1);
}
myDataStream.Bid += new _IDataStreamEvents_BidEventHandler(myDataStream_Bid);
myDataStream.Ask += new _IDataStreamEvents_AskEventHandler(myDataStream_Ask);
}
private static void myDataStream_Bid(int SymbolNr, float Price, DateTime Time)
{
PriceItem p;
p.SymbolNr = SymbolNr;
p.Price = Price;
p.Time = Time;
p.IsBid = true;
Prices.Enqueue(p);
}
private static void myDataStream_Ask(int SymbolNr, float Price, DateTime Time)
{
PriceItem p;
p.SymbolNr = SymbolNr;
p.Price = Kurs;
p.Time = Zeit;
p.IsBid = false;
Prices.Enqueue(p);
}
public static void RestartMyCOMProcess()
{
try
{
Process proc = Process.GetProcessesByName("MyCOMProcess")[0];
proc.Kill();
}
catch (Exception)
{
//No Process = fine
}
MyCOMObjekt = null;
DataStream myDataStream = GetDataStream();
myDataStream.Bid -= new _IDataStreamEvents_BidEventHandler(myDataStream_Bid); //probably not necessary...
myDataStream.Ask -= new _IDataStreamEvents_AskEventHandler(myDataStream_Ask); //probably not necessary...
FillStream(myDataStream);
}
}
Class B:
class B
{
private static int countPrices; //Incremented every time a price is taken out of Price Queue
public static void Initialize(int numberOfWorkerThreads)
{
StartWorkers(numberOfWorkerThreads);
}
public static void StartWorkers(int number)
{
for (int j = 0; j < number; j++)
{
Thread t = new Thread(ScanForPrices);
t.Name = "ScanForPrices" + j;
t.Start();
}
}
private static void ScanForPrices()
{
try
{
while (true)
{
PriceItem p;
if (A.Prices.TryDequeue(out p))
{
if (p.IsBid)
{
AnalyzeBidPrice(p);
}
else
{
HandleAskPrice(p);
}
Interlocked.Increment(ref countPrices)
}
else
{
Thread.Sleep(1);
}
}
}
catch (ThreadAbortException)
{
Console.WriteLine("Price Scan Thread aborted.");
}
}
public static void StartHeartbeatCheck()
{
Thread t = new Thread(CheckHeartBeat);
t.Name = "CheckHeartBeat";
t.Start();
}
private static void CheckHeartBeat()
{
TimeSpan start = new TimeSpan(09, 0, 0); //09 o'clock
TimeSpan end = new TimeSpan(20, 0, 0); //20 o'clock
TimeSpan stopTime = new TimeSpan(20, 5, 0); //20 o'clock and 5 minutes
int countSuccessiveBlockings = 0;
try
{
while (true)
{
Thread.Sleep(5000);
TimeSpan now = DateTime.Now.TimeOfDay;
if ((now > start) && (now < end))
{
int countOld = countPrices;
Thread.Sleep(1000);
if (countOld == countPrices)
{
Console.WriteLine(DateTime.Now + ": Price Stream blocked!");
countSuccessiveBlockings++;
}
else
{
countSuccessiveBlockings = 0;
}
if (countSuccessiveBlockings > 2)
{
A.RestartMyCOMProcess();
countSuccessiveBlockings = 0;
}
}
}
}
catch (ThreadAbortException)
{
Console.WriteLine("Heartbeat Thread aborted.");
}
}
}
This question already has answers here:
Use Unity API from another Thread or call a function in the main Thread
(5 answers)
Closed 6 years ago.
I'm having trouble with a UnityEngine version. (Can't upgrade, game is not mine)
The server RANDOMLY crashes when a specific UnityEngine method is used in a timer/thread (It was fixed in a version, I read It)
It happens totally random, I get a crash log, that starts from the timer/thread and ends at a UnityEngine method. (This never happens when I use It in the main thread)
My question is that Is It possible somehow to call the method from the main thread if the current thread != with the main thread?
Any help is appreciated
This Loom class is able to call the specific method from the Main thread, this is how you do It:
public class Loom : MonoBehaviour
{
public static int maxThreads = 10;
static int numThreads;
private static Loom _current;
private int _count;
public static Loom Current
{
get
{
Initialize();
return _current;
}
}
public void Awake()
{
_current = this;
initialized = true;
}
static bool initialized;
static void Initialize()
{
if (!initialized)
{
if (!Application.isPlaying)
return;
initialized = true;
var g = new GameObject("Loom");
_current = g.AddComponent<Loom>();
}
}
private List<Action> _actions = new List<Action>();
public struct DelayedQueueItem
{
public float time;
public Action action;
}
private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
public static void QueueOnMainThread(Action action)
{
QueueOnMainThread(action, 0f);
}
public static void QueueOnMainThread(Action action, float time)
{
if (time != 0)
{
lock (Current._delayed)
{
Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
}
}
else
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
}
public static Thread RunAsync(Action a)
{
Initialize();
while (numThreads >= maxThreads)
{
Thread.Sleep(1);
}
Interlocked.Increment(ref numThreads);
ThreadPool.QueueUserWorkItem(RunAction, a);
return null;
}
private static void RunAction(object action)
{
try
{
((Action)action)();
}
catch
{
}
finally
{
Interlocked.Decrement(ref numThreads);
}
}
public void OnDisable()
{
if (_current == this)
{
_current = null;
}
}
// Use this for initialization
public void Start()
{
}
List<Action> _currentActions = new List<Action>();
// Update is called once per frame
public void Update()
{
lock (_actions)
{
_currentActions.Clear();
_currentActions.AddRange(_actions);
_actions.Clear();
}
foreach (var a in _currentActions)
{
a();
}
lock (_delayed)
{
_currentDelayed.Clear();
_currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
foreach (var item in _currentDelayed)
_delayed.Remove(item);
}
foreach (var delayed in _currentDelayed)
{
delayed.action();
}
}
}
//Usage
public void Call()
{
if (Thread.CurrentThread.ManagedThreadId != TestClass.MainThread.ManagedThreadId)
{
Loom.QueueOnMainThread(() => {
Call();
});
return;
}
Console.WriteLine("Hello");
}
I am new to multi-thread programming in C#. My problem is that I don't know how to wait for a method that is being run on another thread to finish, before it can continue to the next line. For example, something like this
public class A
{
int i;
public A()
{
i = 0;
}
protected void RunLoop()
{
while(i < 100)
{
i++;
}
}
public void Start()
{
TimerResolution.TimeBeginPeriod(1);
runThread = new Thread(new ThreadStart(RunLoop));
running = true;
runThread.Start();
}
}
public class B
{
A classAInstance = new A();
A.Start();
Console.Writeline(i);
}
Right now, it prints 0 on the console, which is not what I want (i.e. i = 100).
What is the best way to do this? BTW, I don't have access to the runThread that is created in class A
Thanks.
EDIT:
It was a bit difficult to solve this problem without modifying a lot codes. Therefore, we ended up with adding a condition in the public void Start() with which it can decide whether to run the RunLoop in a separate thread or not. The condition was defined using an Enum field.
public void Start()
{
TimerResolution.TimeBeginPeriod(1);
running = true;
if (runningMode == RunningMode.Asynchronous)
{
runThread = new Thread(new ThreadStart(RunLoop));
runThread.Start();
}
else
{
RunLoop();
}
}
And
public enum RunningMode { Asynchronous, Synchronous };
Thanks everyone for help.
The preferred method is to use the Task Parallel Library (TPL) and use Task with await.
If you must use Threads, then use a ManualResetEvent or ManualResetEventSlim to signal the end of a method.
void Main()
{
var a = new A();
a.Start();
a.FinishedEvent.WaitOne();
Console.WriteLine(a.Index);
}
// Define other methods and classes here
public class A
{
ManualResetEvent mre = new ManualResetEvent(false);
int i;
public EventWaitHandle FinishedEvent
{
get { return mre; }
}
public int Index
{
get { return i; }
}
public A()
{
i = 0;
}
protected void RunLoop()
{
while (i < 1000)
{
i++;
}
mre.Set();
}
public void Start()
{
var runThread = new Thread(new ThreadStart(RunLoop));
runThread.Start();
}
}
Your life would be so much better with tasks.
Your code could be this simple:
var task = Task.Factory.StartNew(() =>
{
var i = 0;
while (i < 100)
{
i++;
}
return i;
});
Console.WriteLine(task.Result);
I like use Monitor.Wait() and Monitor.Pulse() in conjunction with "lock" operator. It works, but you must be careful, when you use this technique.
I'm added some changes to your code to demonstrate it. Code below are prints i== 100, as you want.
public class A
{
int i;
public object SyncObject
{ get; private set; }
public A()
{
SyncObject = new object();
i = 0;
}
protected void RunLoop()
{
while (i < 100)
{
i++;
}
lock (SyncObject)
{
Monitor.Pulse(SyncObject);
}
}
public void Start()
{
var runThread = new Thread(new ThreadStart(RunLoop));
runThread.Start();
}
public void PrintI()
{
Console.WriteLine("I == " + i);
}
}
public class B
{
public static void Run()
{
A classAInstance = new A();
lock (classAInstance.SyncObject)
{
classAInstance.Start();
Monitor.Wait(classAInstance.SyncObject);
}
classAInstance.PrintI();
}
}
Desription:
I am adding some data to list every second. After every 10 seconds, the data is saved to the database and then I clear the list. If I stop the timer, I am saving the data remaining in the list and then clearing the list and then stopping the timer.
In the above code, Let's say when I stop the timer after 11 seconds, The Class1s list should have only 1 data, but I see there are 11 datas. Can you guys tell what I am doing wrong here? Maybe my use of lock is incorrect or my code is totally incorrect
public class Class1Singleton
{
private static Class1Singleton Class1Singleton;
private static List<Class1> Class1s;
private static Timer saveClass1Timer;
private static readonly object lock1 = new object();
private Class1Singleton()
{
}
public static Class1Singleton getInstance()
{
if (Class1Singleton == null) {
try
{
Class1Singleton = new Class1Singleton();
}
catch (Exception e){}
}
return Class1Singleton;
}
public void StartTimer()
{
if (saveClass1Timer == null)
{
saveClass1Timer = new Timer(10000);
//saveClass1Timer.Interval = 10000;
saveClass1Timer.Elapsed += new ElapsedEventHandler(SaveClass1);
saveClass1Timer.Enabled = true;
}
}
public void SaveClass1(object sender, ElapsedEventArgs e)
{
try {
lock (lock1)
{
new Class1Repository().InsertAllClass1(Class1s);
ClearWorkoutList();
}
}
catch (Exception ex){}
}
public void InsertClass1(List<Class1> Class1)
{
if (Class1s == null)
{
Class1s = new List<Class1>(Class1);
}
else
{
lock (lock1)
{
Class1s.AddRange(Class1);
}
}
}
public void ClearWorkoutList()
{
if (Class1s != null)
{
Class1s.Clear();
}
}
public void StopTimer()
{
if (Class1s != null && Class1s.Count > 0)
{
lock (lock1)
{
new Class1Repository().InsertAllClass1(Class1s);
ClearWorkoutList();
}
}
if (saveClass1Timer != null && saveClass1Timer.Enabled == true)
{
saveClass1Timer.Stop();
}
}
}
I've made a few changes to your code (see comments):
public class Class1Singleton
{
// This is the way Jon Skeet recommends implementing a singleton in C#
// See http://csharpindepth.com/Articles/General/Singleton.aspx
static readonly Class1Singleton instance = new Class1Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Class1Singleton() { }
// There's only one instance of Class1Singleton so there's
// no advantage in making the members static
private List<Class1> Class1s;
private Timer saveClass1Timer;
private readonly object lock1 = new object();
Class1Singleton()
{
}
public static Class1Singleton Instance
{
get { return instance; }
}
public void StartTimer()
{
// If you're using this class in a multi-thread environment,
// all methods that access the list or timer should be locked
lock (lock1)
{
if (saveClass1Timer == null)
{
saveClass1Timer = new Timer(10000);
//saveClass1Timer.Interval = 10000;
saveClass1Timer.Elapsed += new ElapsedEventHandler(SaveClass1);
saveClass1Timer.Enabled = true;
}
}
}
// SaveClass1 doesn't need to be public
private void SaveClass1(object sender, ElapsedEventArgs e)
{
lock (lock1)
{
SaveWorkoutList();
ClearWorkoutList();
}
}
private void SaveWorkoutList()
{
//new Class1Repository().InsertAllClass1(Class1s);
}
public void InsertClass1(List<Class1> Class1)
{
lock (lock1)
{
if (Class1s == null)
Class1s = new List<Class1>(Class1);
else
Class1s.AddRange(Class1);
}
}
private void ClearWorkoutList()
{
if (Class1s != null)
{
Class1s.Clear();
}
}
public void StopTimer()
{
lock (lock1)
{
if (Class1s != null && Class1s.Count > 0)
{
SaveWorkoutList();
ClearWorkoutList();
}
if (saveClass1Timer != null && saveClass1Timer.Enabled == true)
{
saveClass1Timer.Stop();
}
}
}
}
public class Consumer
{
Queue<int> queue;
Object lockObject;
public Consumer(Queue<int> queue, Object lockObject)
{
this.queue = queue;
this.lockObject = lockObject;
}
public void consume(string filepath)
{
int item = 0;
while (true)
{
lock (lockObject)
{
if (queue.Count == 0)
{
Monitor.PulseAll(lockObject);
continue;
}
item = queue.Dequeue();
if (item == 0)
{
break;
}
//do some staff
}
}
}
}
public class Producer
{
Queue<int> queue;
Object lockObject;
public int ProgressPercent = 0;
int TotalProducedElements = 0;
public bool check1 = false;
public Producer(Queue<int> queue, Object lockObject)
{
this.queue = queue;
this.lockObject = lockObject;
}
private bool IsPrime(int num)
{
if (num == 0)
return true;
num = Math.Abs(num);
for (int i = 2; i <= Math.Sqrt(num); i++)
if (num % i == 0)
return false;
return true;
}
public void produce(int target)
{
try
{
int seq = 0;
while (seq++ < target)
{
lock (lockObject)
{
int item = seq;
if (IsPrime(item))
{
queue.Enqueue(item);
}
TotalProducedElements++;
ProgressPercent = seq;
if (queue.Count == 0)
{
Monitor.PulseAll(lockObject);
}
}
}
queue.Enqueue(0);
}
catch (Exception e)
{
}
}
}
}
private void Start_Click(object sender, EventArgs e)
{
Object lockObj = new object();
Queue<int> queue = new Queue<int>();
Producer p = new Producer(queue, lockObj);
Consumer c = new Consumer(queue, lockObj);
int target = int.Parse(TargetText.Text);
string path = Path.Text;
Thread Thread1 = new Thread(() => p.produce(target));
Thread Thread2 = new Thread(()=>c.consume(path));
Thread1.Start();
Thread2.Start();
progressBar1.Maximum = target;
while(true)
{
if(p.ProgressPercent==0)
{
Thread.sleep(1000);
}
else
{
progressBar1.Value=p.ProgressPercent;
}
}
}
I have two classes working on same queue. one to produce a set of integers and the second is to consume that integers from queue.
And during all this I want to update my progress bar by that percentage.
So how to update progress bar from consumer without blocking for my GUI?
Note I have used progressbar.Invoke and delegate but didn't work.
You need two things. First is obviously a thread, the other is invoker.
Invokers will let you change window's controls from inside of a thread. Here's the example:
Invoke((MethodInvoker)delegate
{
Label1.text = "asd";
}
Threads are ran like this:
some_thread = new Thread
(delegate()
{
{
//some_thread code
}
});
some_thread.Start();
You also need to add using System.Threading; at the beginning of the file.
So, the final code should look like this:
some_thread = new Thread
(delegate()
{
{
for(;;)
{
Invoke((MethodInvoker)delegate
{
//update the progress bar here
}
}
}
});
some_thread.Start();
You could use a BackgroundWorker (System.ComponentModel) to accomplish this easily. Take a look at:
http://www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demo
Clear:
while(true)
{
if(p.ProgressPercent==0)
{
Thread.sleep(1000);
}
else
{
progressBar1.Value=p.ProgressPercent;
}
}
Replace:
ProgressPercent = seq;
to
UpdateProgres(seq);
Add:
public void UpdateProgres(int _value)
{
if (InvokeRequired)
{
Invoke(new Action<int>(UpdateProgres), _value);
return;
}
progressBar1.Value = _value;
}
Summary your needed function;
public void UpdateProgres(int _value)
{
if (InvokeRequired)
{
Invoke(new Action<int>(UpdateProgres), _value);
return;
}
progressBar1.Value = _value;
}
Or need Lock the value. For Example;
while(true)
{
lock (p.ProgressPercent)
{
int _p = p.ProgressPercent;
}
if(_p==0)
{
Thread.sleep(1000);
}
else
{
progressBar1.Value=_p;
}
}