Threading Parallel Invoke, Action - c#

My code as below
public void DownloadConcurrent(Action<string> Methord)
{
Action<string>[] methordList = new Action<string>[Concurent_Downloads];
for (int i = 0; i < Concurent_Downloads; i++)
{
methordList[i] = Methord;
}
Parallel.Invoke(methordList);
}
Parallel.Invoke is giving error:
"cannot convert from 'System.Action<string>[]' to 'System.Action[]'"
The Method it is calling is
public void DownloadLinks(string Term)
{
}

check Parallel.ForEach like the following
static void Main(string[] args)
{
List<string> p = new List<string>() { "Test", "Test2", "Test3"};
Parallel.ForEach(p, Test);
}
public static void Test(string test)
{
Debug.WriteLine(test);
}
This should do the trick for you
HTH
Dominik

In your case it is easier if you use
Parallel.ForEach
over your string list instead of using
Parallel.Invoke
with additional parameter. Let me know if you want to stick to Parallel.Invoke.

Parallel.Invoke accepts Action array while your code is passing it an Action<string> array. What you can do is :
public void DownloadConcurrent(Action<string> Methord)
{
Action<string>[] methordList = new Action<string>[Concurent_Downloads];
var r = methordList.Select(a => (Action)(() => a("some_str"))).ToArray();
Parallel.Invoke(r);
}
You need to replace some_str with proper value for each action

Related

Getting Collection was modified; enumeration operation may not execute. exception

Getting Collection was modified; enumeration operation may not execute. exception
Code:
public static string GetValue(List<StateBag> stateBagList, string name)
{
string retValue = string.Empty;
if (stateBagList != null)
{
foreach (StateBag stateBag in stateBagList)
{
if (stateBag.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
{
retValue = stateBag.Value;
}
}
}
return retValue;
}
getting this exception some time times not every time at this place.
stacktrace:
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource
resource)
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at Tavisca.TravelNxt.Shared.Entities.StateBag.GetValue(List`1 stateBagList, String name)
#no one i have tried for following code but still getting exception
code:
class StateBag
{
public string Name;
public string Value;
}
class Program
{
static List<StateBag> _concurrent = new List<StateBag>();
static void Main()
{
var sw = new Stopwatch();
try
{
sw.Start();
Thread thread1 = new Thread(new ThreadStart(A));
Thread thread2 = new Thread(new ThreadStart(B));
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
sw.Stop();
}
catch (Exception ex)
{
}
Console.WriteLine("Average: {0}", sw.ElapsedTicks);
Console.ReadKey();
}
private static Object thisLock = new Object();
public static string GetValue(List<StateBag> stateBagList, string name)
{
string retValue = string.Empty;
if (stateBagList != null)
{
lock (thisLock)
{
foreach (StateBag stateBag in stateBagList)
{
if (stateBag.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
{
retValue = stateBag.Value;
}
}
}
}
return retValue;
}
static void A()
{
for (int i = 0; i < 5000; i++)
{
_concurrent.Add(new StateBag() { Name = "name" + i, Value = i.ToString() });
}
}
static void B()
{
for (int i = 0; i < 5000; i++)
{
var t = GetValue(_concurrent, "name" + i);
}
}
}
Getting Collection was modified; enumeration operation may not execute. exception
Reason: This exception occurs when the enumeration that you are looping through is modified in same thread or some other thread.
Now, in the code that you have provided there isnn't any such scenario. Which means that you might be calling this in a multi-threaded environment and collection is modified in some other thread.
Solution: Implement locking on your enumeration so that only one thread gets access at a time. Something like this should do it.
private static Object thisLock = new Object();
public static string GetValue(List<StateBag> stateBagList, string name)
{
string retValue = string.Empty;
if (stateBagList != null)
{
lock(thisLock)
{
foreach (StateBag stateBag in stateBagList)
{
if (stateBag.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
{
retValue = stateBag.Value;
}
}
}
}
return retValue;
}
Although locking is the right way to go for fixing the original implementation, there might be a better approach altogether which will involve a lot less code and potential bugs.
The following demo console app uses ConcurrentDictionary instead of List, and is fully threadsafe without the need for your own locking logic.
It also offers better performance, as a dictionary lookup is much faster than serially searching a list:
class StateBag
{
public string Name;
public string Value;
}
class Program
{
public static string GetValue(ConcurrentDictionary<string, StateBag> stateBagDict, string name)
{
StateBag match;
return stateBagDict.TryGetValue(name.ToUpperInvariant(), out match) ?
match.Value : string.Empty;
}
static void Main(string[] args)
{
var stateBagDict = new ConcurrentDictionary<string, StateBag>();
var stateBag1 = new StateBag { Name = "Test1", Value = "Value1" };
var stateBag2 = new StateBag { Name = "Test2", Value = "Value2" };
stateBagDict[stateBag1.Name.ToUpperInvariant()] = stateBag1;
stateBagDict[stateBag2.Name.ToUpperInvariant()] = stateBag2;
var result = GetValue(stateBagDict, "test1");
Console.WriteLine(result);
}
}
This is happening because some other thread in your application is modifying the stateBagList. There are 2 thing you can do... either use locking around your code block where you refer the stateBagList or you can make a deep copy of stateBagList in GetValues method and then use the new list in your for loop.
As already suggested you need to place a lock around the enumeration.
However that action is only effective if you also lock around the statements that are modifying the collection.
static void A()
{
for (int i = 0; i < 5000; i++)
{
lock(thisLock)
{
_concurrent.Add(new StateBag() { Name = "name" + i, Value = i.ToString() });
}
}
}
Otherwise all you are doing is ensuring that only one thread can enumerate the collection at a time. A single thread or multiple other threads could still be modifying the collection while this single enumeration takes place.
I'd also recommend the following link:
http://www.albahari.com/threading/part2.aspx#_Thread_Safety_and_NET_Framework_Types
Other tips:
It is possible to lock on the collection itself like so:
lock(_concurrent) { //statements}
And the GetValue method can be simplified like so:
public static string GetValue(List<StateBag> stateBagList, string name)
{
if (stateBagList != null)
{
lock (thisLock)
{
return stateBagList.FirstOrDefault
(x => x.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
}
}
}
return string.Empty;
}
Replace List with SynchronizedCollection. It is thread-safe collection class.
It does this via locking so that you essentially have a List where every access is wrapped in a lock statement.

Turning strings into commands?

Is there a convenient way to take variables and convert them into something readable by the code? What I have right now reads somewhat like this:
int buttonNumber = 3;
int buttonShow = 0;
ButtonChanger bC;
void Update () {
if(buttonNumber == 1) {
buttonShow = bC.Change1;
}
if(buttonNumber == 2) {
buttonShow = bC.Change2;
}
if(buttonNumber == 3) {
buttonShow = bC.Change3;
}
What I would like to be able to do is more like this:
int buttonNumber = 3;
int buttonShow = 0;
ButtonChanger bC;
void Update () {
buttonShow = ("bC.Change" + buttonNumber).toCode();
}
Something like this?
using System;
namespace ConsoleApplication1
{
enum ButtonChanger
{
Change1 = 1,
Change2 = 2,
Change3 = 3
}
class Program
{
static void Main(string[] args)
{
var changer = GetButtonChanger(2);
Console.WriteLine(changer);
Console.WriteLine((int)changer);
}
private static ButtonChanger GetButtonChanger(int i)
{
return (ButtonChanger)Enum.Parse(typeof(ButtonChanger), string.Format("Change{0}", i));
}
}
}
try using Dictionary<>. It will allow you to have key value pair. so your key would be bC.Change and you can retrive key using Key() method
eg
Dictionary<string, int> data = new Dictionary<string, int>();
data.Add("Change1", 123);
data.Add("Change2", 456);
foreach (string key in data.Keys)
{
Console.WriteLine(key);
}
I am not sure if I understand you right but given your title ... into commands I assume you are looking for a generic way to execute the methods in ButtonChanger.
If your ButtonChanger class is of type Component or GameObject you can use the SendMessage method:
MyClass.cs
const string ButtonShowPrefix = "Change";
ButtonChanger bC;
void Update () {
bC.SendMessage (ButtonShowPrefix + buttonNumber, SendMessageOptions.DontRequireReceiver);
}
ButtonChanger.cs
void Change1 () {
// do stuff for button 1
}
void Change2 () {
// do stuff for button 2
}
Note that it is possible to pass a parameter to the called method but there is no way to return a value. So if you need state information you have to work around this by using a public member in ButtonChanger.
As SendMessage is considered as somewhat expensive you should avoid unnecessary calls in case that no action has to be taken.
If things are getting more complex I would suggest combining this with gulshanm01 approach of using a dictionary for mapping identifiers to methods.

Send multiple objects between threads using invoke in c#

I'm having problems with passing loaded data from one thread to another to add the data to the form. I added another object into "var obj = new object[] { names }" and got "Parameter count mismatch". I'd still prefer to pass "Clients" and "Messages" from "LoadData()" in the second thread to "UpdateFormMethod()" in the first one, but I have no idea how to do it. I'd be grateful if anyone could help me with this problem.
Here's the important part of the code within one class:
private readonly Thread _thread;
public readonly Loader Loader = new Loader();
public Dictionary<string, Client> Clients;
public Dictionary<string, Message> Messages;
private bool _stopData = false;
public delegate void UpdateForm(object data);
public UpdateForm MyDelegate;
public Fcon() {
InitializeComponent();
MyDelegate = new UpdateForm(UpdateFormMethod);
_thread = new Thread(LoadData);
_thread.Start();
}
public void UpdateFormMethod(object data) {
foreach (var str in ((IEnumerable<string>)data).Where(str => !fcon_container_users_list.Items.Contains(str))) {
fcon_container_users_list.Items.Insert(0, str);
}
}
public void LoadData() {
while (!_stopData) {
Clients = Loader.GetClients(Operator);
Messages = Loader.GetMessages(Operator);
var status = Loader.SetStatus(Operator);
var names = new string[Clients.Count];
var x = 0;
foreach (var kvp in Clients) {
names[x] = "user_" + kvp.Value.id_fcon_client;
x++;
}
var obj = new object[] { names };
this.Invoke(this.MyDelegate, obj);
Thread.Sleep(1000);
}
}
public void StopData() {
_stopData = true;
}
It sounds like you're not entirely clear where the signature is coming from. It's your own delegate - if you want to change the signature, just change the signature of the delegate and the method implementing it:
public delegate void UpdateForm(IEnumerable<string> data, int foo);
...
public void UpdateFormMethod(IEnumerable<string> data, int foo) {
foreach (var str in data.Where(str =>
!fcon_container_users_list.Items.Contains(str))) {
fcon_container_users_list.Items.Insert(0, str);
}
}
Then:
var obj = new object[] { names, someIntVariable };
this.Invoke(this.MyDelegate, obj);
Or more simply:
this.Invoke(this.MyDelegate, names, someIntVariable);
I'd probably use the existing Action<T>, Action<T1, T2> delegates rather than creating new ones though OR T Func<T1 [,T2]> if you require a return type.
you are passing an object [] in but you should only pass in object.
To send it in just cast it as object i.e.
this.Invoke(this.MyDelegate, (object)obj);
and cast it back inside the method. The reason they specified object as the parameter type is that it allows them not to have to specify many many signatures I think

working with threads - add to collection

List<int> data=new List<int>();
foreach(int id in ids){
var myThread=new Thread(new ThreadStart(Work));
myThread.Start(id);
}
Work(){
}
Method Work does some processing on the received id and then adds the result to the data list? How can I add data to the collection from each thread? How would my code look like? thanks
If you're using .NET 4, I strongly suggest you use Parallel Extensions instead. For example:
var list = ids.AsParallel()
.Select(Work)
.ToList();
where Work is:
public int Work(int id)
{
...
}
so that it can receive the id appropriately. If you're not keen on the method conversion, you could add a lambda expression:
var list = ids.AsParallel()
.Select(id => Work(id))
.ToList();
Either way, this will avoid creating more threads than you really need, and deal with the thread safety side of things without you having to manage the locks yourself.
First of all, you need to protect your multithreaded access with a lock. Second, you need to pass the parameter to your thread (or use lambda which can capture the local variable; beware that if you capture loop variable, it will change the value during the loop, so you ought to have a local copy).
object collectionLock = new object();
List<int> data = new List<int>();
foreach (int id in ids)
{
Thread t = new Thread(Worker);
t.Start(id);
}
void Worker(object o)
{
int id = (int)o;
lock(collectionLock)
{
data.Add(id);
}
}
you can pass and retrieve data (using callbacks) from threads. See MSDN article.
Example:
public class SomeClass
{
public static List<int> data = new List<int>();
public static readonly object obj = new object();
public void SomeMethod(int[] ids)
{
foreach (int id in ids)
{
Work w = new Work();
w.Data = id;
w.callback = ResultCallback;
var myThread = new Thread(new ThreadStart(w.DoWork));
myThread.Start();
}
}
public static void ResultCallback(int d)
{
lock (obj)
{
data.Add(d);
}
}
}
public delegate void ExampleCallback(int data);
class Work
{
public int Data { get; set; }
public ExampleCallback callback;
public void DoWork()
{
Console.WriteLine("Instance thread procedure. Data={0}", Data);
if (callback != null)
callback(Data);
}
}

Implement VB With statement in C#

How would you create an extension method which enables me to do the following (warning: exteme pseudo-code)...
class FooBar
{
Int32 Foo { get; set; }
String Bar { get; set; }
}
new FooBar().With(fb => new Func<FooBar, Object>(instance =>
{
// VB With magic
// NOTE: The instance parameter HAS to be by reference
instance.Foo = 10;
instance.Bar;
return new Object();
}));
If you could specify anonymous functions without a return type (void), the above would look much cleaner...
new FooBar().With(fb => new Func<FooBar, void>(instance =>
{
instance.Foo = 10;
instance.Bar;
}));
This is pseudo-code of the worst kind. But I hope you get the idea.
To specify anonymous methods without return type, use Action<T> instead of Func<T, TResult>:
new FooBar().With(new Action<FooBar>(instance =>
{
instance.Foo = 10;
instance.Bar;
}));
(I don't quite see the point in this particular case, but I take your word on the pseudo code part...)
Update
Full example for being complete:
The extension method:
public static void With<T>(this T input, Action<T> action)
{
action(input);
}
Sample usage
new FooBar().With(fb =>
{
fb.Foo = 10;
fb.Bar = "some string";
});
Note that you don't need to explicitly declare the Action<FooBar>, the compiler figures that out. Should you wish to, for clarity, the call would look like this:
new FooBar().With<FooBar>(new Action<FooBar>(fb =>
{
fb.Foo = 10;
fb.Bar = "some string";
}));
Maybe this will help:
new FooBar().With( fb=> {
fb.Foo = 10;
fb.Bar = fb.Foo.ToString();
} );
// ... somewhere else ...
public static void With<T>( this T target, Action<T> action ) {
action( target );
}
As you asked how to write the extension, here goes
public static void With<T>(this T target, Action<T> action) where T : class
{
action(target);
}
Personally dont see what benefit this has, but fill yer boots!
How about just
return new FooBar{ Foo=10; };

Categories