Click here to Skip to main content
15,065,324 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have an asynchronous BindingList which isn't threadSafe. I've been trying all wkend to make it threadSafe but I seem to be going no where! Does anyone know how to make BindingList threadSafe or where I can find a threadSafe implementation?

Thanks in advance,
-DA
Posted
Updated 17-Jun-12 11:07am
v3

The only way to make this thread safe is to apply a lock on the add method:

C#
void AddItemToList(object o)
{
    lock(myBindingList)
    {
        myBindingList.Add(o);
    }
}


If you are looking for a thread safe collection then take a look at the system.threading.concurrent namespace. http://msdn.microsoft.com/en-us/library/dd287108[^] these provide thread safe collections. does that help?
   
Comments
d.allen101 17-Jun-12 17:06pm
   
thx for the lock suggestion db7uk but unfortunately dataBinding won't acknowledge my lock...the bindingList "ListChange" will still fire and the UI will try and update causing an Cross Thread Expection...
db7uk 17-Jun-12 17:39pm
   
damn sorry. It was a long shot as I got the feeling you probably tried that already.

Ok, so what flavor is it? WPF/winforms? Have you tried adding a field that when set true you could ignore in the Listchanged event?
d.allen101 17-Jun-12 17:46pm
   
i'm using winForms...I've thought/attempted to suspend ListChanged but I'm not sure how to go about that exactly...won't that cause my grid to miss updates? here's my custom bindingList. you'll notice in the "ApplySortCore" method I have "this.RaiseListChangeEvents = false" at the beginning of the code then I reset it to True at the end of the block...I did this because I was getting an index out to range when I sort...not sure if this is correct. Would you please take a look at my code and let me what's wrong here?

<pre>
[Serializable]
public class AsyncBindingList<t> : BindingList<t>//: ThreadSafeBindingList<t>
{
[NonSerialized]
bool isSortedValue;
[NonSerialized]
ListSortDirection sortDirectionValue;
[NonSerialized]
PropertyDescriptor sortPropertyValue;
[NonSerialized]
ArrayList sortedList;
[NonSerialized]
ArrayList unsortedItems;

[NonSerialized]
ISynchronizeInvoke control;

public AsyncBindingList(ISynchronizeInvoke control)
{
this.control = control;
}

delegate void ListChangedDelegate(ListChangedEventArgs e);

protected override void OnListChanged(ListChangedEventArgs e)
{
if (control.InvokeRequired)
{
//IAsyncResult asyncResult = invoke.BeginInvoke(new ListChangedDelegate(base.OnListChanged), new object[] { e });
control.Invoke(new ListChangedDelegate(base.OnListChanged), new object[] { e });
}
else
base.OnListChanged(e);
}

protected override bool SupportsSearchingCore
{
get { return true; }
}

protected override bool SupportsSortingCore
{
get { return true; }
}

protected override bool IsSortedCore
{
get { return isSortedValue; }
}

protected override PropertyDescriptor SortPropertyCore
{
get { return sortPropertyValue; }
}

protected override ListSortDirection SortDirectionCore
{
get { return sortDirectionValue; }
}

protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
this.RaiseListChangedEvents = false;

sortedList = new ArrayList();

// check to see if the property implements IComparable interface
Type interfaceType = prop.PropertyType.GetInterface("IComparable");

if (interfaceType != null)
{
sortPropertyValue = prop;
sortDirectionValue = direction;

unsortedItems = new ArrayList(this.Count);

foreach (object item in this.Items)
{
sortedList.Add(prop.GetValue(item));
unsortedItems.Add(item);
}

sortedList.Sort();
T temp;

if (direction == ListSortDirection.Descending)
sortedList.Reverse();

for (int i = 0; i < this.Count; i++)
{
int pos = Find(prop.Name, sortedList[i]);
if (pos != i)
{
temp = this[i];
this[i] = this[pos];
this[pos] = temp;
}
}

isSortedValue = true;

OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));

this.RaiseListChangedEvents = true;
}
else
throw new NotSupportedException("Cannot sort by " + prop.Name );
}

protected override int FindCore(PropertyDescriptor prop, object key)
{
// Get the property info for the specified property.
Sys
The concurrent containers don´t have all the methods that a List or a BindingList does, so, using the lock seens to be the best way for most purposes.
   
I know the post is old but maybe someone else is looking , Synchronization context can help.

Provides a thread-safe binding-list by using the synchronizationcontext where the list was created.
https://searchcode.com/codesearch/view/2515598/[^]
   
Take a look at this it might be a better implementation than the 'hack' I posted earlier.. but I don't know have not tested them yet.

from Larry at
http://stackoverflow.com/questions/12532877/asynchronously-add-value-to-bindinglist-cross-threading-locking-issue[^]

C#
public class BindingListInvoked<t> : BindingList<t>
{
    public BindingListInvoked() { }

    private ISynchronizeInvoke _invoke;
    public BindingListInvoked(ISynchronizeInvoke invoke) { _invoke = invoke; }
    public BindingListInvoked(System.Collections.Generic.IList<t> items) { this.DataSource = items; }
    delegate void ListChangedDelegate(ListChangedEventArgs e);

    protected override void OnListChanged(ListChangedEventArgs e)
    {

        if ((_invoke != null) && (_invoke.InvokeRequired))
        {
            IAsyncResult ar = _invoke.BeginInvoke(new ListChangedDelegate(base.OnListChanged), new object[] { e });
        }
        else
        {
            base.OnListChanged(e);
        }
    }
    public System.Collections.Generic.IList<t> DataSource
    {
        get
        {
            return this;
        }
        set
        {
            if (value != null)
            {
                this.ClearItems();
                RaiseListChangedEvents = false;

                foreach (T item in value)
                {
                    this.Add(item);
                }
                RaiseListChangedEvents = true;
                OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
            }
        }
    }
}
   
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900