在我的应用中,当点击Button
时会触发Command
下载image
(异步......我希望)和strings
,{{1 }和name
,如下所示。下载这些项目的功能是从character
调用的:
DispatcherTimer
在这种方法中,我有:
timer.Tick += myMethodToDownloadCastInfo;
在 timer.Stop();
List<CastWithPic> castWithPicList = new List<CastWithPic>();
// Add name and id for each CastWithPic in the list
// ..
_viewModel.SelectedItem.castInfoWithPics = castWithPicList;
// Download all the required pics
var tasks = new List<Task>();
foreach (CastWithPic cast in castWithPicList)
{
tasks.Add(downloadBitmap(cast.profilePath, cast.id));
}
await Task.WhenAll(tasks);
函数中,我将对象downloadBitmap
SelectedItem's
设置为保存castInfoWithPics
值。
此时我收到错误:
image
The calling thread cannot access this object because a different thread owns it.
在我的SelectedItem
中声明。
ViewModel
班级
SelectedItem
public List<CastWithPic> castInfoWithPics { get; set; }
班级
CastWithPic
public string name
{
get { return (string)this.GetValue(nameProperty); }
set
{
this.SetValue(nameProperty, value);
}
}
public static readonly DependencyProperty nameProperty = DependencyProperty.Register(
"name", typeof(string),
typeof(CastWithPic));
public string character
{
get { return (string)this.GetValue(characterProperty); }
set
{
this.SetValue(characterProperty, value);
}
}
public static readonly DependencyProperty characterProperty = DependencyProperty.Register(
"character", typeof(string),
typeof(CastWithPic));
public Bitmap image
{
get { return (Bitmap)this.GetValue(imageProperty); }
set
{
this.SetValue(imageProperty, value);
}
}
public static readonly DependencyProperty imageProperty = DependencyProperty.Register(
"image", typeof(Bitmap),
typeof(CastWithPic));
downloadBitmap
我的问题是:
为什么当我在HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
RequestState myRequestState = new RequestState();
myRequestState.request = request;
// Start the asynchronous request.
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(RespCallback), Tuple.Create(myRequestState, actorID));
// this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, DefaultTimeout, true);
// The response came in the allowed time. The work processing will happen in the
// callback function.
allDone.WaitOne();
方法中分配_viewModel.SelectedItem.castInfoWithPics = castWithPicList;
但我在timer
方法中出错时,我没有收到错误。
Task
是否也开始新timer
?
在这种情况下,解决问题的正确方法是使用此处建议的解决方案吗?
The calling thread cannot access this object because a different thread owns it
答案 0 :(得分:1)
我认为需要在UI线程中设置_viewModel.SelectedItem.castInfoWithPics = castWithPicList
。您的donloadBitmap
函数使用回调来处理响应,并在ThreadPool
线程上运行。
您可以使用Dispatcher.Invoke
强制在UI线程上进行工作。尝试将其放入回调中并将相应的代码放入注释部分:
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
new Action(() => /* set selected item */));
要获得更好的解决方案,您可以使用async-await
来恢复当前SynchronizatonContext
,并且您不需要使用Dispatcher.Invoke
。 HttpClient
提供了一个可以使用的异步友好API。
以下是设置TextBox值的简单示例。
private async Task DownloadUrlAsync(string url)
{
using (HttpClient httpClient = new HttpClient())
{
textBox1.Text = await httpClient.GetStringAsync(url);
}
}
答案 1 :(得分:-2)
你必须冻结你的对象,问题就解决了。 这是一个示例:
videoIcon = new BitmapImage();
videoIcon.BeginInit();
videoIcon.UriSource = new Uri(@"C:\Data\Image1.jpg");
videoIcon.DecodePixelWidth = 14;
videoIcon.EndInit();
videoIcon.Freeze();
没有Freeze(),我收到了您收到的相同错误消息。使用Freeze()可以解决问题
更多信息在这里:
https://msdn.microsoft.com/en-us/library/ms750509(v=vs.110).aspx
&#34;冻结的Freezable也可以在线程之间共享,而未冻结的Freezable则不能。[&#34;