Timer和Task是否创建新线程?

时间:2015-01-24 02:42:57

标签: c# wpf multithreading asynchronous task

在我的应用中,当点击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

2 个答案:

答案 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.InvokeHttpClient提供了一个可以使用的异步友好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;