Mar*_*cel 7 c# wpf multithreading pixelsense mvvm-light
我正在尝试从我的wpf应用程序中加载来自Web的图像.
这个想法如下:当我点击一个按钮时,会弹出一个包含附加信息的弹出窗口.在这个弹出窗口中,我正在使用网络上的一些图像.
问题:当加载弹出窗口时,系统会在等待图像时挂起.我正在绑定我背后的代码中的图像.图像存储在ObservableCollection中.我尝试使用线程来加载图像,但每次我遇到一个异常,说线程不是对象的所有者.
我尝试使用Invoke将下载的图像下载到UserinterfaceThread但我无法访问它.我的代码如下:
IList<Image> imagesFromWeb = downloadImagesFromWeb(url);
DispatcherHelper.UIDispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate()
{
foreach (Image img in imagesFromWeb
{
this.ObservableCollection_Images.Add(img);
}
}
Run Code Online (Sandbox Code Playgroud)
下载图像并尝试将图像添加到(已打开的)弹出窗口后,我得到异常,说该线程不是对象的所有者
有人可以指出我正确的方向吗?
Isa*_*avo 15
如果您可以在公共Web服务器上使用可以使用普通HTTP URI进行处理的映像,则可以将源直接设置为:
<Image Source="http://www.someserver.com/myimage.png" />
Run Code Online (Sandbox Code Playgroud)
WPF将负责下载它 - 它甚至会异步地进行下载我认为虽然我不是100%肯定.
你当然也可以通过数据绑定来做到这一点:
<Image Source="{Binding TheImage}" />
Run Code Online (Sandbox Code Playgroud)
并在viewmodel中
public string TheImage
{
get { return "http://www.someserver.com/myimage.png"; }
}
Run Code Online (Sandbox Code Playgroud)
您可能会遇到有关集合、WPF、绑定和线程的各种问题
最好的事情(在我看来)是使用调度程序安全的可观察集合
这是一个实现,还包括线程安全:
public class SafeObservable<T> : IList<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
private readonly IList<T> collection = new List<T>();
private readonly Dispatcher dispatcher;
public event NotifyCollectionChangedEventHandler CollectionChanged;
public event PropertyChangedEventHandler PropertyChanged;
private readonly ReaderWriterLock sync = new ReaderWriterLock();
public SafeObservable()
{
dispatcher = Dispatcher.CurrentDispatcher;
}
public void Add(T item)
{
if (Thread.CurrentThread == dispatcher.Thread)
DoAdd(item);
else
dispatcher.BeginInvoke((Action)(() => DoAdd(item)));
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Count"));
}
private void DoAdd(T item)
{
sync.AcquireWriterLock(Timeout.Infinite);
collection.Add(item);
if (CollectionChanged != null)
CollectionChanged(this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
sync.ReleaseWriterLock();
}
public void Clear()
{
if (Thread.CurrentThread == dispatcher.Thread)
DoClear();
else
dispatcher.BeginInvoke((Action)(DoClear));
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Count"));
}
private void DoClear()
{
sync.AcquireWriterLock(Timeout.Infinite);
collection.Clear();
if (CollectionChanged != null)
CollectionChanged(this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
sync.ReleaseWriterLock();
}
public bool Contains(T item)
{
sync.AcquireReaderLock(Timeout.Infinite);
var result = collection.Contains(item);
sync.ReleaseReaderLock();
return result;
}
public void CopyTo(T[] array, int arrayIndex)
{
sync.AcquireWriterLock(Timeout.Infinite);
collection.CopyTo(array, arrayIndex);
sync.ReleaseWriterLock();
}
public int Count
{
get
{
sync.AcquireReaderLock(Timeout.Infinite);
var result = collection.Count;
sync.ReleaseReaderLock();
return result;
}
}
public bool IsReadOnly
{
get { return collection.IsReadOnly; }
}
public bool Remove(T item)
{
if (Thread.CurrentThread == dispatcher.Thread)
return DoRemove(item);
var op = dispatcher.BeginInvoke(new Func<T, bool>(DoRemove), item);
if (op == null || op.Result == null)
return false;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Count"));
return (bool)op.Result;
}
private bool DoRemove(T item)
{
sync.AcquireWriterLock(Timeout.Infinite);
var index = collection.IndexOf(item);
if (index == -1)
{
sync.ReleaseWriterLock();
return false;
}
var result = collection.Remove(item);
if (result && CollectionChanged != null)
CollectionChanged(this, new
NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
sync.ReleaseWriterLock();
return result;
}
public IEnumerator<T> GetEnumerator()
{
return collection.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return collection.GetEnumerator();
}
public int IndexOf(T item)
{
sync.AcquireReaderLock(Timeout.Infinite);
var result = collection.IndexOf(item);
sync.ReleaseReaderLock();
return result;
}
public void Insert(int index, T item)
{
if (Thread.CurrentThread == dispatcher.Thread)
DoInsert(index, item);
else
dispatcher.BeginInvoke((Action)(() => DoInsert(index, item)));
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Count"));
}
private void DoInsert(int index, T item)
{
sync.AcquireWriterLock(Timeout.Infinite);
collection.Insert(index, item);
if (CollectionChanged != null)
CollectionChanged(this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
sync.ReleaseWriterLock();
}
public void RemoveAt(int index)
{
if (Thread.CurrentThread == dispatcher.Thread)
DoRemoveAt(index);
else
dispatcher.BeginInvoke((Action)(() => DoRemoveAt(index)));
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Count"));
}
private void DoRemoveAt(int index)
{
sync.AcquireWriterLock(Timeout.Infinite);
if (collection.Count == 0 || collection.Count <= index)
{
sync.ReleaseWriterLock();
return;
}
collection.RemoveAt(index);
if (CollectionChanged != null)
CollectionChanged(this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
sync.ReleaseWriterLock();
}
public T this[int index]
{
get
{
sync.AcquireReaderLock(Timeout.Infinite);
var result = collection[index];
sync.ReleaseReaderLock();
return result;
}
set
{
sync.AcquireWriterLock(Timeout.Infinite);
if (collection.Count == 0 || collection.Count <= index)
{
sync.ReleaseWriterLock();
return;
}
collection[index] = value;
sync.ReleaseWriterLock();
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
15113 次 |
最近记录: |