ok, so I'm writing a duplicate logon "worker" class in C# and I've ran into a bit of a snag. My logic behind it, I thought, was flawless! :(
But, I can't for the life of me figure out why it's triggering on the first occurence rather than on just duplicates :(
namespace Lab.Core.BackgroundWorker {
using Lab.Core;
using Lab.Core.Net;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
public class MultiLogon : IWorker {
private static Hashtable LoggedOnUsers = new Hashtable();
private Thread _worker = null;
//private Thread m_UsersUpdate = null;
public delegate Boolean AddUserToCollectionDelegate(String user, String computer);
public delegate void ClearCollectionDelegate(String user);
public delegate Boolean IsUserLoggedInDelegate(String user);
public Boolean AddUserToCollection(String user, String computer) {
int retVal = MultiLogon.LoggedOnUsers.Count + 1;
if (String.IsNullOrEmpty(user) || String.IsNullOrEmpty(computer))
return false;
if (!MultiLogon.LoggedOnUsers.ContainsKey(user))
MultiLogon.LoggedOnUsers.Add(user, computer);
return (MultiLogon.LoggedOnUsers.Count == retVal);
}
public void ClearCollection() {
if (MultiLogon.LoggedOnUsers.Count > 0)
MultiLogon.LoggedOnUsers.Clear();
}
public Boolean IsUserLoggedIn(String user) {
if (String.IsNullOrEmpty(user))
return false;
return (LoggedOnUsers.Contains(user));
}
#region IWorker Members
public void Run(object obj) {
AddUserToCollectionDelegate add = new AddUserToCollectionDelegate(AddUserToCollection);
//ClearCollectionDelegate clear = new ClearCollectionDelegate(ClearCollection);
//IsUserLoggedInDelegate isLogged = new IsUserLoggedInDelegate(IsUserLoggedIn);
while (true) {
foreach (Computer c in ComputerList.Instance)
if (!add.Invoke(c.UserName, c.MachineName)) {
// duplicate! or not? :/
// Credit (through adoption of code) goes to:
// http://bytes.com/groups/net-c/263778-quickly-finding-duplicates-arraylist#post1059834
foreach (DictionaryEntry item in MultiLogon.LoggedOnUsers) {
MessageBox.Show((String)item.Key, (String)item.Value);
//NetworkMessage.Send((String)item.Value, String.Format("It is against lab policy to share your account with anyone other than yourself or use someone else's account! Logout immediately or further action will be taken. Your action has been logged."));
//OffenseManager.Instance.AddOffense((String)item.Key, null, String.Format("Account sharing - Computer: {0}", item.Value), false);
}
}
Thread.Sleep(750);
}
}
public void Start() {
_worker = new Thread(new ParameterizedThreadStart(Run));
_worker.IsBackground = true;
_worker.Start();
}
public void Stop() {
if (_worker.IsAlive)
_worker.Abort();
}
#endregion
}
}
Apologies for the long code file. I don't know exactly what to paste to help you guys help me. :/
Thanks in advance! :)
Could be a thread race condition.
Have you tried to lock the collection when you're searching/inserting into it?
I don't believe Hashtable are threadsafe.
You might want to put a
lock(this) {
}
block around anything accessing the hashtable.
Related
I'm trying to make a game with two players in WPF, that are controlled with WASD/ arrow keys and can move on the game field. When a control key of first player is pressed while second player is already moving (key is down), the second player stops moving. But I'd like them to move simultaneously.
MainWindow.xaml.cs:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
//Player1
if(Keyboard.IsKeyDown(Key.W)) GameVM.MovePlayer("1W");
if (Keyboard.IsKeyDown(Key.S)) GameVM.MovePlayer("1S");
if (Keyboard.IsKeyDown(Key.A)) GameVM.MovePlayer("1A");
if (Keyboard.IsKeyDown(Key.D)) GameVM.MovePlayer("1D");
//Player2
if (Keyboard.IsKeyDown(Key.Up)) GameVM.MovePlayer("2W");
if (Keyboard.IsKeyDown(Key.Down)) GameVM.MovePlayer("2S");
if (Keyboard.IsKeyDown(Key.Left)) GameVM.MovePlayer("2A");
if (Keyboard.IsKeyDown(Key.Right)) GameVM.MovePlayer("2D");
}
I would do it with an external class from c++ (I guess it is c++) and a main class where all the threads get started from.
For 1 Player you would need 1 class or even better 1 struct which contains the states for the keys aswell as the specific buttons you want for it (changeable because of variables, maybe consider settings.txt/json to safe the new keys etc....)
Key Settings and State Class:
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Media; //Maybe you dont need some of them but you will see it in your IDE if you use them or not
namespace GAME.Settings
{
public class Settings //standard Values and states for the keys
{
internal struct SettingsPlayer1
{
public static Keys UPkey = Keys.A; //List https://learn.microsoft.com/en-en/dotnet/api/system.windows.forms.keys?view=netcore-3.1
public static Keys LEFTkey = Keys.A;
public static Keys DOWNkey = Keys.S;
public static Keys RIGHTkey = Keys.D;
public static bool UP = false; //key states
public static bool LEFT = false;
public static bool DOWN = false;
public static bool RIGHT = false;
}
internal struct SettingsPlayer1
{
public static Keys UPkey = Keys.UP;
public static Keys LEFTkey = Keys.LEFT;
public static Keys DOWNkey = Keys.DOWN;
public static Keys RIGHTkey = Keys.RIGHT;
public static bool UP = false; //key states
public static bool LEFT = false;
public static bool DOWN = false;
public static bool RIGHT = false;
}
}
}
Get Key State class
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using GAME.Settings;
namespace GAME.Keys
{
internal class Imports //imports from .dll
{
[DllImport("user32.dll")]
public static extern short GetAsyncKeyState(Keys vKey); //needed to get the async Key state
}
public class GetKeysPressedP1
{
static bool GetAsyncKeyState(Keys key) => Imports.GetAsyncKeyState(key) != 0;
public static void Run() //this is the method which the thread will run
{
while (true)
{
Thread.Sleep(5); //you can choose your sleep time for input delay
if (GetAsyncKeyState(Settings.SettingsPlayer1.UPkey)) Settings.SettingsPlayer1.UP = true;
else Settings.SettingsPlayer1.UP = false;
if (GetAsyncKeyState(Settings.SettingsPlayer1.LEFTkey)) Settings.SettingsPlayer1.LEFT = true;
else Settings.SettingsPlayer1.LEFT = false;
if (GetAsyncKeyState(Settings.SettingsPlayer1.DOWNkey)) Settings.SettingsPlayer1.DOWN = true; //you could also do something in here like move to x direction etc.
else Settings.SettingsPlayer1.DOWN = false;
if (GetAsyncKeyState(Settings.SettingsPlayer1.RIGHTkey)) Settings.SettingsPlayer1.RIGHT = true;
else Settings.SettingsPlayer1.RIGHT = false;
}
}
}
}
Main Class
using System;
using System.Threading;
using GAME.Keys;
using GAME.Settings;
namespace GAME.Main
{
public class main //can be any class in which the thread will be created and started
{
public main()
{
public static Thread GetKeysPressedThreadP1 = new Thread(GetKeysPressedP1.Run); //new thread
GetKeysPressedThreadP1.Start(); //starting the new thread in the background
while(true)
{
//Do Something with it if(GAME.Settings.SettingsPlayer1.UP){ P1.position.x++;}
}
}
}
}
As I've done this on notepad right now, I can not check if everything is right, I will check it in 20mins but maybe this will already help you
If you have questions regarding this code, just ask.
If this is all wrong or makes no sense in this specific case, feel free to edit or mark it so I can either delete or edit it because I'm not an expert in c# myself:)
Hope you can help me with this one.i am beginner in multithreading programming with C#.
I am trying to build a program to write all numbers from range 1 to 2000 in two text files using two threads.
Every thread should write number from 1 to 2000 that not found at any of the two files "there is no duplicated numbers in the files" and every thread should't write the number that have been wrote by the another thread.
At the end if we merged the numbers of the two files we should have the numbers from 1 to 2000
Here is the source code i am trying but there is a problem in the writing for loop in the below image
i can't handle the process of writing by the two synchronized threads and i had exception:
Object synchronization method was called from an unsynchronized block of code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
namespace Multithreading
{
class Program
{
static TextWriter file2 = new StreamWriter("file2 location");
static TextWriter file1 = new StreamWriter("file1 location");
static void Main(string[] args)
{
try
{
int[] array = new int[2000];
Thread thread1 = new Thread(Program.writeinfile1);
Thread thread2 = new Thread(Program.writeinfile2);
for (int counter = 1; counter <= 2000; counter++)
{
thread1.Start(counter);
thread2.Start(++counter);
Monitor.Enter(thread1);
Monitor.Wait(thread1);
Monitor.PulseAll(thread2);
}
}
catch (FileNotFoundException)
{
Console.WriteLine("the file you are trying to open is not found");
}
}
public static void writeinfile1(object x)
{
int converttointx = (int)x;
file1.WriteLine(converttointx);
file1.Close();
}
public static void writeinfile2(object y)
{
int converttointy = (int)y;
file2.WriteLine(converttointy);
file2.Close();
}
}
}
Here's an example of multi-threaded calls talking to one another to ensure they don't duplicate work.
I've not done exactly what you've asked for, since this looks quite homeworky; but hopefully this will help you to figure out the solution to your issue...
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace StackOverflow
{
class Program
{
static void Main(string[] args)
{
new Program();
Console.WriteLine("done");
Console.ReadKey();
}
Program()
{
int noThreads = 5;
int target = 2000;
StartThread(noThreads, target);
}
//kicks off our threads / waits for all threads to complete before returning
void StartThread(int noThreads, int target)
{
int id = noThreads--;
if (id > 0)
{
Doer doer = new Doer(id, target);
Thread t = new Thread(doer.Do);
t.Start();
StartThread(noThreads,target);
t.Join();
}
}
}
class Doer
{
static int marker = 0;
static readonly object syncLocker = new object();
readonly int id;
readonly int target;
public Doer(int id, int target)
{
this.id = id;
this.target = target;
}
public void Do()
{
while (marker < this.target)
{
int i;
lock (syncLocker)
{
i = ++marker;
}
System.Console.WriteLine("{0:00}: {1:###0}", id, i);
//Thread.Sleep(RandomNo()); //uncomment this & code below if your threads are taking turns / behaving too predictably
}
}
/*
static readonly Random rnd = new Random();
static readonly object rndSyncLocker = new object();
public static int RandomNo()
{
lock (rndSyncLocker)
{
return rnd.Next(0, 1000);
}
}
*/
}
}
You are not using the Monitor class correctly. The call to Monitor.PulseAll(thread2); should be called within thread the thread which owns the lock, which in this case would be within the writeinfile1 and writeinfile2 method.
This is why you are getting the exception:
Object synchronization method was called from an unsynchronized block of code.
See the following StackOverflow question for the correct way to use Monitor.PulseAll(object):
Help needed in Monitor.PulseAll()
Suppose I have a WeakReference of a target strong reference. I'd like to be informed when the target object itself is being collected by the GC. Is it possible?
EDIT: Adding code to the finalizer/destructor is not an option here. I need something that is not dependent on class code.
It's possible under .NET 4.0 and following using ConditionalWeakTable<TKey, TValue>. Thanks this, and other sites. It follows proof of concept code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
namespace Test
{
public static class GCInterceptor
{
private static ConditionalWeakTable<object, CallbackRef> _table;
static GCInterceptor()
{
_table = new ConditionalWeakTable<object, CallbackRef>();
}
public static void RegisterGCEvent(this object obj, Action<int> action)
{
CallbackRef callbackRef;
bool found = _table.TryGetValue(obj, out callbackRef);
if (found)
{
callbackRef.Collected += action;
return;
}
int hashCode = RuntimeHelpers.GetHashCode(obj);
callbackRef = new CallbackRef(hashCode);
callbackRef.Collected += action;
_table.Add(obj, callbackRef);
}
public static void DeregisterGCEvent(this object obj, Action<int> action)
{
CallbackRef callbackRef;
bool found = _table.TryGetValue(obj, out callbackRef);
if (!found)
throw new Exception("No events registered");
callbackRef.Collected -= action;
}
private class CallbackRef
{
private int _hashCode;
public event Action<int> Collected;
public CallbackRef(int hashCode)
{
_hashCode = hashCode;
}
~CallbackRef()
{
Action<int> handle = Collected;
if (handle != null)
handle(_hashCode);
}
}
}
}
Tested with the following code:
public partial class Form1 : Form
{
private object _obj;
public Form1()
{
InitializeComponent();
_obj = new object();
_obj.RegisterGCEvent(delegate(int hashCode)
{
MessageBox.Show("Object with hash code " + hashCode + " recently collected");
});
}
private void button1_Click(object sender, EventArgs e)
{
_obj = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
What about Object.Finalize() method? Won't that be invoked upon finalization?
You may use interception to catch Finalize for each classes which is inherited from a custom interface/class. I think, this is what you want to try to achieve, right? You can use Unity for that. Here is a very short example how to do interception with Unity.
I have a multi threaded program that opens a few threads to query an external CRM and save the results in an in-memory IDictionary in order to speed up the system.
I'm a little confused about multi threading and critical sections. I want my class QueryThreadProcess to have a thread which runs the query and to manage starting and stopping the query. It has an object of type query and saves the results in a list.
The class QueryManager will kill all the processes or start all processes, basically collection wide methods.
I have a feeling that the private members for QueryThreadProcess are shared between all threads. How would I be able to make them private to each thread, but also kill each thread separately from an external class?
I don't want to lock because I want all the threads to run parallel.
Here is my manager class:
public class QueryManager
{
private IDictionary<int, QueryThreadProcess> _queries;
public QueryManager()
{
_queries = new Dictionary<int, QueryThreadProcess>();
}
public void Start()
{
CreateQueryThreadsFromDb();
StartAllThreads();
}
private void StartAllThreads()
{
if (_queries != null && _queries.Count > 0)
{
StopThreadsAndWaitForKill();
}
foreach (var query in _queries)
query.Value.Start();
}
private void CreateQueryThreadsFromDb()
{
var queries = new QueryProvider().GetAllQueries();
if (_queries != null && _queries.Count > 0)
{
StopThreadsAndWaitForKill();
_queries.Clear();
}
foreach (var query in queries)
_queries.Add(query.Id, new QueryThreadProcess(query));
}
private void StopThreadsAndWaitForKill()
{
KillAllThreads();
while (!AreAllThreadsKilled()) { }
}
private void KillAllThreads()
{
foreach (var query in _queries)
query.Value.Kill();
}
private bool AreAllThreadsKilled()
{
return _queries.All(query => query.Value.IsKilled);
}
public IList<User> GetQueryResultById(int id)
{
return _queries[id].Result;
}
}
and here is my class for QueryProcesses which holds the threads that do the actual query:
using System.Collections.Generic;
using System.Threading;
using Intra.BLL.MessageProviders;
using Intra.BO;
using Intra.BO.Messages;
namespace Intra.BLL.QueryProcess
{
internal class QueryThreadProcess
{
private readonly Thread _thread;
private readonly Query _query;
private bool _isStoppingQuery = false;
private bool _isKilled = true;
private IList<User> _result;
private readonly object _objSync = new object();
public QueryThreadProcess(Query query)
{
_query = query;
_thread = new Thread(RetrieveQueries);
}
public void Start()
{
_isStoppingQuery = true;
while (!_isKilled) { }
_isStoppingQuery = false;
_thread.Start();
}
private void RetrieveQueries()
{
const string BROKERNAME = "bla";
_isKilled = false;
while (!_isStoppingQuery)
{
Broker broker = new BrokerProvider().GetBrokerByName(BROKERNAME);
var users = new QueryProvider().GetUserObjectsByQuery(_query, ParaTokenGenerator.GetBrokerAuthToken(broker));
_result = users;
}
_isKilled = true;
}
public bool IsKilled
{
get { return _isKilled; }
}
public IList<User> Result
{
get
{
lock (_objSync)
return _result;
}
}
public void Kill()
{
_isStoppingQuery = true;
}
}
}
It doesn't really answer your question, but it looks like a more modern approach using the Task Parallel Library of .NET 4 could save you some headache. Controlling Threads by yourself isn't necessary. It looks like you could refactor your classes to a few lines of code and get rid of the described problems.
.NET 4 has ThreadLocal<T> which may be of interest to you
The _thread and _query fields probably don’t matter as they are declared readonly and are not changed after each thread is run. These are not shared between worker threads as they are private to the class and you create a separate instance of the class for each thread.
_isStoppingQuery and _isKilled are accessed by both the worker thread and the controlling thread. As such these should be declared volatile to ensure they are not cashed in a processor register and don’t suffer from execution reordering.
There is a potential issue with _result. The lock in Result/get is not enough to protect the contents of _result. It is only protecting the reference to the list not the list itself. However as your worker thread is only overwriting the reference each cycle it may not be an issue. I would probably do away with the lock on _objSync and declare _result volatile too.
I have two classes: Action class, that has a method for executing VBScript files, and Item class that contains a list of Action instances. My problem is that I want to limit the number of VBScript files that can be run at the same time. I have no experience with this, and I have googled and searched around, but found nothing. My only idea of how to do is is presented here:
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
namespace Test
{
public class Action
{
public string Script;
public static int Limit;
public static int ActiveCount = 0;
public Process process = new Process();
public Action(string script)
{
Script = script;
}
public void Execute()
{
process.EnableRaisingEvents = true;
process.Exited += new EventHandler(Handler);
try
{
if (ActiveCount < Limit)
{
process = Process.Start(
"c:\\windows\\system32\\wscript.exe",
"\"" + Script + "\"");
ActiveCount++;
}
}
catch(Win32Exception e)
{
}
}
private void Handler(
object sender, EventArgs e)
{
ActiveCount--;
}
}
public class Item
{
public ArrayList Actions = new ArrayList();
}
class Program
{
static void Main()
{
Action.Limit = 5;
Item item = new Item();
item.Actions.Add(
new Action("C:\\Scripts\\Test_1.vbs"));
for (int i = 0; i < 10; i++)
{
foreach (Action action in item.Actions)
{
action.Execute();
Console.WriteLine(Action.ActiveCount);
}
}
}
}
}
The requirement of limiting the number of created processes seems common to me, but as I said, I haven't been able to find any samples I could build on. My question is: what is the common or usual way of doing this? (I also haven't been able to find any samples here on StackOverFlow, so if there are any, please post the link). Any hint or a link is welcome.
Well what you've got will work.
I'm not sure what the fact that you can't find more information tells you.
It's either that you're trying to solve a non-problem - but if your scripts are large and complex or need access to shared resources then limiting the number that run would seem to be a good idea; or it's that your solution is the right one and it's so trivial no one else has thought to raise it.