In my application I pass List lst1 into ProgressChanged handler of the a BackGroundWorker.
Inside of handler I need to exploit lst1 for refreshing datagridview. But lst1 is changing in permanence inside of background process.
So I can't directly use lst1, because it's reference-type object and any changes in background process will impact ProgressChanged handler, where lst1 is supposed to be constant.
The solution is: once inside of ProgressChanged handler, assign lst1 to some local list lst2.
Surprisingly, none of the List copying methods works.
I've tried the following:
1. List
2. List
3. List
lst2.AddRange(lst1);
In all cases ArgumentException is generated with the following message:
Destination array was not long enough. Check destIndex and length, and the array's lower bounds.
Thanks in advance.
Pavel.

PavelPosted Sep 25, 2012, 5:42 AM
if (bins_count % 1000 == 0 && bins_count > 0)
{
lock (padLock)
{
List
progr_struct_item.bins_count = bins_count;
progr_struct_item.routed_cases = routed_best_case_item;
progr_struct_item.routed_layers = routed_layers_best;
bw.ReportProgress(1, progr_struct_item);
}
}
Thanks Vulpes !
VulpesPosted Sep 24, 2012, 11:50 AM
PavelPosted Sep 24, 2012, 11:11 AM
int row_max = (Routed_Best_Cases.Count <= 100) ? Routed_Best_Cases.Count : 100;
dgv_BestCases.Rows.Clear();
for (int i = 0; i < row_max; i++)
{
dgv_BestCases.Rows.Add(1);
for (int n = 0; n < SFP.Length; n++)
{
try
{
dgv_BestCases.Rows[i].Cells[n].Value = Routed_Best_Cases[i].SFP_layout[n];
dgv_BestCases.Rows[i].Cells[n].Style.ForeColor = Routed_Best_Cases[i].SFP_mirror[n] ?
Color.Blue : Color.Red;
}
catch (ArgumentOutOfRangeException)
{
Debug.WriteLine("SFP i = {0};\tn = {1};\tRows = {2};\trouted_cases = {3}", i, n, dgv_BestCases.Rows.Count, Routed_Best_Cases.Count);
}
}
for (int n = 0; n < Molex_Conn.Length; n++)
{
try
{
dgv_BestCases.Rows[i].Cells[SFP.Length + n].Value = Routed_Best_Cases[i].Track_Order[n].type ==
tx_rx.TX ? "TX" : "RX" + Routed_Best_Cases[i].Track_Order[n].channel.ToString();
dgv_BestCases.Rows[i].Cells[SFP.Length + n].Style.ForeColor = Routed_Best_Cases[i].Track_Order[n].tap !=
taps.DOWN ? Color.Red : Color.Blue;
}
catch (ArgumentOutOfRangeException)
{
Debug.WriteLine("Molex i = {0};\tn = {1};\tRows = {2};\trouted_cases = {3}", i, n, dgv_BestCases.Rows.Count, Routed_Best_Cases.Count);
}
}
}
VulpesPosted Sep 24, 2012, 11:00 AM
PavelPosted Sep 24, 2012, 9:56 AM
PavelPosted Sep 24, 2012, 9:32 AM
Maybe I've missed something, but 1st solution doesn't work. Here is piece of code from bg-process:
if (bins_count % 1000 == 0)
{
progr_struct_item.bins_count = bins_count;
progr_struct_item.routed_cases = Routed_Best_Cases;
bw.ReportProgress(1, progr_struct_item);
}
As you see, I assign the list (routed_cases field in structure) just before calling handler. The esception is the same as mentionned in my previous message.
Will try to follow your second proposition.
Thanks.
P.S. Once more what a ridiculuous past feature in this forum. I participated in many of forums... Never seen code formatting as here. Or putting a code just not supported??? I've contacted site administration. Still no answer.
VulpesPosted Sep 24, 2012, 9:14 AM
However, I don't see any need to pass the copied list as a parameter to the ProgressChanged handler. I'd just define it as a field of your class so that it's accessible from any method in the class.
PavelPosted Sep 24, 2012, 8:28 AM
Yes, in the background thread I do some manipulations with list:
add new elements
when some condition is met, the list is cleared
What I can't understand why there is no mean to create some "fixed detached copy" of list in the background thread and pass it as parameter into Progress handler ?
VulpesPosted Sep 24, 2012, 8:18 AM
If you're just adding elements (and possibly reading them ), then we might be able to attack this in a different way though I'll refrain from producing any code till I hear from you on this.
PavelPosted Sep 24, 2012, 7:39 AM
List<Routed_Case> curr_routed_cases = null;
lock (padLock)
{
curr_routed_cases =
new List<Routed_Case>(((ProgressStruct)e.UserState).routed_cases);
}
The exception is generated inside of lock(padLock).
P.S. The message editing facilities are terrible. Maybe something wrong in my browser ...
VulpesPosted Sep 24, 2012, 7:27 AM
Can you either try again or just post any code where you're doing something with the list.
PavelPosted Sep 24, 2012, 6:43 AM
Please see zip-attachment.
PavelPosted Sep 24, 2012, 6:40 AM
PavelPosted Sep 24, 2012, 6:39 AM
VulpesPosted Sep 24, 2012, 6:19 AM
You'll need to add this static field to your form:
private static object padLock = new object();
Now change the code which copies the list to the following:
List
lock(padLock)
{
lst2 = new List
}
Notice that this only creates a 'shallow copy' in that the SomeType1 objects within the list are not themselves copied - only the references to them are copied.
PavelPosted Sep 24, 2012, 6:09 AM
No, I don't do this.
First, I don't master well multithreading.
Second, I try to find some technique, that allow to do create "instant flash copy" lst2 of a list lst1. lst1 is continually changing in the bg-process, but lst2 should be equal to the lst1 in the moment of assignement, and then detached. This detached value I want to pass in handler.
Is this second approach feasible ?
Regards.
VulpesPosted Sep 24, 2012, 5:55 AM
When you attempt to copy the list are you using a lock, to prevent the background worker from changing the list concurrently?
PavelPosted Sep 24, 2012, 5:48 AM
SomeType1[] some_type1_arr = new SomeType1[some_type1_lst.Count];
some_type1_lst.CopyTo(some_type1_arr);
While 1st instruction is executing, the List some_type1_lst changes its lenght in the background process: when exception occurs and I check the length of some_type1_arr and count of some_type1_lst, the values are: 422 and 475 correspondingly.
So the main problem is how to pass some_type1_lst into ProgressChanged handler by value !!!
Regards.
Pavel.