Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 更新列表框结果为;无效的跨线程访问。”;_C#_Windows_Windows Phone 7_Windows Phone 8 - Fatal编程技术网

C# 更新列表框结果为;无效的跨线程访问。”;

C# 更新列表框结果为;无效的跨线程访问。”;,c#,windows,windows-phone-7,windows-phone-8,C#,Windows,Windows Phone 7,Windows Phone 8,我正在构建rss提要阅读器。我使用Visual studio创建了一个入门应用程序。在它的主页上,我添加了一个指向新pivot页面的链接。所有rss事件都发生在我的pivot页面中。现在,在我的rss提要列表框中,我最初使用以下代码设置了一些列表项: public PivotPage1() { InitializeComponent(); getMeTheNews(); addToCollection("Android is going up","TechCrunch")

我正在构建rss提要阅读器。我使用Visual studio创建了一个入门应用程序。在它的主页上,我添加了一个指向新pivot页面的链接。所有rss事件都发生在我的pivot页面中。现在,在我的rss提要列表框中,我最初使用以下代码设置了一些列表项:

public PivotPage1()
{
    InitializeComponent();
    getMeTheNews();
    addToCollection("Android is going up","TechCrunch");
    lstBox.DataContext = theCollection;
}

private void addToCollection(string p1, string p2)
{
    theCollection.Add(new NewsArticle(p1,p2));
}
下面是另外两个函数,rss是从服务器获取并解析的,但是当我想在
getTheResponse()
方法中将处理过的条目添加到
observeCollection
中时,它会导致无效的跨线程访问错误。有什么想法吗

代码:

private void getMethNews()
{
字符串url=”http://rss.cnn.com/rss/edition.rss";
HttpWebRequestWebRequest=(HttpWebRequest)HttpWebRequest.Create(url);
BeginGetResponse(getTheResponse,webRequest);
}
private void getTheResponse(IAsyncResult结果)
{
HttpWebRequest request=result.AsyncState作为HttpWebRequest;
if(请求!=null)
{
尝试
{
WebResponse=request.EndGetResponse(结果);
XDocument doc=XDocument.Load(response.GetResponseStream());
IEnumerable articles=文件子体(“项目”);
foreach(条款中的var条款){
系统.诊断.调试.编写(文章);
尝试
{
System.Diagnostics.Debug.WriteLine(article.Element(“title”).Value);
addToCollection(article.Element(“title”).Value,“CNN”);
}
捕获(NullReferenceException e){
系统.诊断.调试.写线(如StackTrace);
}
}
}
捕获(WebE例外){
System.Diagnostics.Debug.WriteLine(例如StackTrace.ToString());
}
}
其他的
{ 
}
}

您需要使用
调度程序
从非UI线程访问
控件

Deployment.Current.Dispatcher.BeginInvoke(()=>
{ 
     addToCollection(article.Element("title").Value,"CNN");   
});

跨线程收集同步

将列表框绑定到一个可观察集合,当数据更改时,您会更新列表框,因为INotifyCollectionChanged已实现。 dell的ObservableCollection的缺陷在于,数据只能由创建它的线程更改

SynchronizedCollection不存在多线程问题,但不会更新列表框,因为它未在INotifyCollectionChanged中实现,即使实现INotifyCollectionChanged,也只能从创建它的线程调用CollectionChanged(this,e)。。所以它不起作用

结论

-如果希望列表是自动更新的单线程请使用可观察收集

-如果希望列表不是自动更新的,而是多线程的,请使用同步收集

-如果两者都需要,请以以下方式使用Framework 4.5、BindingOperations.EnableCollectionsSynchronization和ObservableCollection():

/ / Creates the lock object somewhere
private static object _lock = new object () ;
...
/ / Enable the cross acces to this collection elsewhere
BindingOperations.EnableCollectionSynchronization ( _persons , _lock )
完整样本

您可以使用调度程序ObservableCollection开始,同时更改收集方法的覆盖范围

public class MyObservableCollectionOverrideCollChangOfObjects<T> : ObservableCollection<T>
    {
        ...

#region CollectionChanged
public override event NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
    var eh = CollectionChanged;
    if (eh != null)
    {
        Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
                                    let dpo = nh.Target as DispatcherObject
                                    where dpo != null
                                    select dpo.Dispatcher).FirstOrDefault();

        if (dispatcher != null && dispatcher.CheckAccess() == false)
        {
            dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
        }
        else
        {
            foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
                nh.Invoke(this, e);
        }
    }
}
#endregion
..
}
公共类MyObservableCollectionOverrideCollChangof对象:ObservableCollection
{
...
#区域集合已更改
公共覆盖事件NotifyCollectionChangedEventHandler CollectionChanged;
CollectionChanged上的受保护覆盖无效(NotifyCollectionChangedEventArgs e)
{
var eh=集合更改;
如果(eh!=null)
{
Dispatcher Dispatcher=(来自eh.GetInvocationList()中的NotifyCollectionChangedEventHandler nh)
让dpo=nh.Target作为DispatcherObject
其中dpo!=null
选择dpo.Dispatcher).FirstOrDefault();
if(dispatcher!=null&&dispatcher.CheckAccess()=false)
{
调用(DispatcherPriority.DataBind,(Action)(()=>OnCollectionChanged(e));
}
其他的
{
foreach(eh.GetInvocationList()中的NotifyCollectionChangedEventHandler nh)
调用(本,e);
}
}
}
#端区
..
}
public class MyObservableCollectionOverrideCollChangOfObjects<T> : ObservableCollection<T>
    {
        ...

#region CollectionChanged
public override event NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
    var eh = CollectionChanged;
    if (eh != null)
    {
        Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
                                    let dpo = nh.Target as DispatcherObject
                                    where dpo != null
                                    select dpo.Dispatcher).FirstOrDefault();

        if (dispatcher != null && dispatcher.CheckAccess() == false)
        {
            dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
        }
        else
        {
            foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
                nh.Invoke(this, e);
        }
    }
}
#endregion
..
}