解决  异步方法没有't work

加入
10月24日,2020年
消息
16
编程经验
Beginner
我面临着问题,试图为函数执行设置超时。

我有以下代码:
Function call:
public BitmapImage[,] GetResult(List<BitmapImage> list)
        {
            var task = Task.Run(() => GetBestPuzzleImage(list));
            if (task.Wait(TimeSpan.FromSeconds(10)))
                return task.Result as BitmapImage[,];
            else
                throw new Exception("Timed out");
        }

Method getBestpulextImage() 创建大呼叫堆栈的函数,其中参数 列表 继续通过功能,直到它得到最后一点 getpixels() ,我试图获得每种格式 清单 元素。还有这个地方,在哪里 system.invalidOperationException:'调用线程无法访问此对象,因为不同的线程拥有它。 被抛出:
C#:
private PixelColor[,] GetPixels(BitmapSource source)
        {
                if (source.Format != PixelFormats.Bgra32)      //here exception is thrown
                {
                    source = new FormatConvertedBitmap(source, PixelFormats.Bgra32, null, 0);
                }

                int width = source.PixelWidth;
                int height = source.PixelHeight;
                PixelColor[,] result = new PixelColor[width, height];

                source.CopyPixels(result, width * 4, 0, true);

                return result;
        }

以下是来自UI线程的函数调用:
C#:
var arr = alghoritm.GetResult(bmp);

我试着用来使用 冻结() 以这种方式制作对象交叉线程的方法:
C#:
private PixelColor[,] GetPixels(BitmapSource source)
{
    source.Freeze();
    var temp = source.Clone();
    
    //and then code works with "temp" value
}

但没有任何改变。所以我想知道为什么会发生这个问题以及如何解决它?
 
Solution
If your code is in a Window then the Window itself provides the ability to marshal a call to the UI thread. There's no specific need to use the control you want to affect. Any control created on that same thread will do.

If your code is not directly UI-aware then you can use the SynchronizationContext class. Basically, you initialise a field of that type using SynchronizationContext.Current and you can always use that field to marshal a method call back to the thread that the current object was created on. Obviously, you would need to have created the current object on the UI thread for that to be useful.

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
In your method : private PixelColor[,] GetPixels(BitmapSource source) you will need to 邀请 物体。

您尝试访问的对象是在另一个线程的其他位置创建的。您需要委派回到创建对象的线程。您可以在此处找到一些示例代码,其中我解释了如何执行此操作: 回答 - 如果在标签的背景颜色上的否则声明。

I try to use to use 冻结() 以这种方式制作对象交叉线程的方法:
冻结不用于此目的。如果我记得,它可以防止修改物品。而且您已经被阻止,因为它是在新任务上执行的代码,而不通过另一种方法锁定对象。
 
加入
10月24日,2020年
消息
16
编程经验
Beginner
In your method : private PixelColor[,] GetPixels(BitmapSource source) you will need to 邀请 物体。

您尝试访问的对象是在另一个线程的其他位置创建的。您需要委派回到创建对象的线程。您可以在此处找到一些示例代码,其中我解释了如何执行此操作: 回答 - 如果在标签的背景颜色上的否则声明。


冻结不用于此目的。如果我记得,它可以防止修改物品。而且您已经被阻止,因为它是在新任务上执行的代码,而不通过另一种方法锁定对象。
我尝试了解决方案,首先,我意识到了这一点 bitmapsource. 不包含任何定义 invoke() 方法。所以我创建了pixeldelagate:
C#:
private delegate PixelColor[,] PixelDelegate(BitmapSource el);
并以这种方式叫他:
C#:
private BitmapSource GetRightImage(BitmapSource first, List<BitmapSource> list, ref double totalDifference)
{
            PixelDelegate pixelDelegate = GetPixels;
            PixelColor[,] left = pixelDelegate.Invoke(first);
            //TODO:
}
也许我错误地解释了你的解决方案,因为抛出了例外。
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,703
地点
悉尼,澳大利亚
编程经验
10+
Note that, these days, you pretty much never have to declare your own delegate types. Just use the appropriate Action (for void methods) or Func. In your case, a Func<BitmapSource, PixelColor[,]> would do the job.
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,703
地点
悉尼,澳大利亚
编程经验
10+
If your code is in a Window then the Window itself provides the ability to marshal a call to the UI thread. There's no specific need to use the control you want to affect. Any control created on that same thread will do.

If your code is not directly UI-aware then you can use the SynchronizationContext class. Basically, you initialise a field of that type using SynchronizationContext.Current and you can always use that field to marshal a method call back to the thread that the current object was created on. Obviously, you would need to have created the current object on the UI thread for that to be useful.
 
解决方案
最佳 底部