&引用;进行调用的子进程无法访问此对象,因为所有者是另一个线程;异常异步/等待WPF C#

&引用;进行调用的子进程无法访问此对象,因为所有者是另一个线程;异常异步/等待WPF C#,c#,.net,wpf,xaml,async-await,C#,.net,Wpf,Xaml,Async Await,我有以下代码: SecondLog.Opacity = 1; List<Reporte> Reportes =await Task.Run(() => db_data.TraerReportes(Environment.MachineName, PickFecha.SelectedDate.Value.Date.ToShortDateString())); if (Reportes.Count != 0) { DataTable dt = ne

我有以下代码:

SecondLog.Opacity = 1;
List<Reporte> Reportes =await Task.Run(() => db_data.TraerReportes(Environment.MachineName, PickFecha.SelectedDate.Value.Date.ToShortDateString()));
    if (Reportes.Count  != 0)
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("Nombre del Proceso");
        dt.Columns.Add("Tiempo Activo");
        dt.Columns.Add("Hora del Ultimo Reporte");
        foreach (Reporte R in Reportes)
        {
            TimeSpan a = TimeSpan.FromSeconds(R.TiempoActivo);
            var Columna = dt.NewRow();
            Columna["t1"] = R.NombreProceso;
            Columna["t2"] = a.ToString(@"hh\:mm\:ss");
            Columna["t3"] = R.Fecha;

            dt.Rows.Add(Columna);
            }
            GridReportes.DataContext = dt.DefaultView;
        }
SecondLog.Opacity=1;
List Reportes=wait Task.Run(()=>db_data.traerrreportes(Environment.MachineName,PickFecha.SelectedDate.Value.Date.toSortDateString());
如果(Reportes.Count!=0)
{
DataTable dt=新的DataTable();
dt.列。添加(“程序名称”);
dt.列添加(“Tiempo Activo”);
dt.Columns.Add(“Hora del Ultimo Reporte”);
foreach(报告中的报告)
{
TimeSpan a=TimeSpan.FromSeconds(R.TiempoActivo);
var Columna=dt.NewRow();
列[“t1”]=R.NombreProceso;
列[“t2”]=a.ToString(@“hh\:mm\:ss”);
柱状体[“t3”]=R.Fecha;
dt.行。添加(列A);
}
GridReportes.DataContext=dt.DefaultView;
}
这将返回:

进行调用的子进程无法访问此对象,因为所有者是第2行的另一个“线程”异常(列表报告=等待任务.Run(()=>db_SpixService.TraerReportes(Environment.MachineName,PickFecha.SelectedDate.Value.Date.ToShortDateString());)


这是为什么?

发生此异常是因为它位于GUI线程之外的另一个线程上

您可以将访问GUI的代码包装在此
(您可以使用实际的窗口对象引用来更改此):

不是最优的,但是你可以试试这个

DateTime myDate;
this.Dispatcher.Invoke(() =>
{
    // Your UI code here
    SecondLog.Opacity = 1;
    myDate = PickFecha.SelectedDate.Value.Date;
});

List<Reporte> Reportes = await Task.Run(() => db_data.TraerReportes(Environment.MachineName, myDate.ToShortDateString()));
if (Reportes.Count != 0)
{
    DataTable dt = new DataTable();
    dt.Columns.Add("Nombre del Proceso");
    dt.Columns.Add("Tiempo Activo");
    dt.Columns.Add("Hora del Ultimo Reporte");
    foreach (Reporte R in Reportes)
    {
        TimeSpan a = TimeSpan.FromSeconds(R.TiempoActivo);
        var Columna = dt.NewRow();
        Columna["t1"] = R.NombreProceso;
        Columna["t2"] = a.ToString(@"hh\:mm\:ss");
        Columna["t3"] = R.Fecha;

        dt.Rows.Add(Columna);
    }

    this.Dispatcher.Invoke(() =>
    {
        GridReportes.DataContext = dt.DefaultView;
    });         
}
DateTime-myDate;
this.Dispatcher.Invoke(()=>
{
//您的UI代码在这里
SecondLog.Opacity=1;
myDate=PickFecha.SelectedDate.Value.Date;
});
List Reportes=wait Task.Run(()=>db_data.TraerReportes(Environment.MachineName,myDate.ToShortDateString());
如果(Reportes.Count!=0)
{
DataTable dt=新的DataTable();
dt.列。添加(“程序名称”);
dt.列添加(“Tiempo Activo”);
dt.Columns.Add(“Hora del Ultimo Reporte”);
foreach(报告中的报告)
{
TimeSpan a=TimeSpan.FromSeconds(R.TiempoActivo);
var Columna=dt.NewRow();
列[“t1”]=R.NombreProceso;
列[“t2”]=a.ToString(@“hh\:mm\:ss”);
柱状体[“t3”]=R.Fecha;
dt.行。添加(列A);
}
this.Dispatcher.Invoke(()=>
{
GridReportes.DataContext=dt.DefaultView;
});         
}
最好是将其分开,只在Invoke中设置GUI元素

//这是不能在另一个线程上运行的部分,所以请准备它
// this is the part that cannot run on another thread, so prepare it
string param = PickFecha.SelectedDate.Value.Date.ToShortDateString();

List<Reporte> Reportes = await Task.Run(() => 
    db_data.TraerReportes(Environment.MachineName, param));
string param=PickFecha.SelectedDate.Value.Date.ToSortDateString(); 列表报告=等待任务。运行(()=> db_data.TraerReportes(Environment.MachineName,param));
您不需要任何其他更改,您不应该需要
Control.Invoke()


假设TraerReportes没有UI工作。

我不能使用wait Task.Run(()=>db_data.TraerReportes(Environment.MachineName,PickFecha.SelectedDate.Value.Date.toSortDateString());在Dispatchereded中,检查是否有帮助。谢谢!非常好:)。你能解释一下你做了什么吗?不要使用
Invoke
返回UI线程,只需返回datatable并在
wait
之后设置DataContext。这就是
wait
的目的-返回到原始线程/sync context w不阻止对
Dispatch.Invoke()的调用
这里在任务之外。它们本质上不是操作,除非整个代码被另一个线程调用。只是不要尝试在
任务内设置DataContext。运行
。返回datatable并在等待后设置它。这就是
等待
的目的。更好的是,修改
TraerrReportes
,并使其成为异步方法。ADO.NET和实体框架都具有异步功能,例如ExecuteReaderAsync而不是ExecuteAsync。
任务。运行
会浪费等待数据库响应的线程。
ExecuteReaderAsync
不过是一个真正的异步功能
// this is the part that cannot run on another thread, so prepare it
string param = PickFecha.SelectedDate.Value.Date.ToShortDateString();

List<Reporte> Reportes = await Task.Run(() => 
    db_data.TraerReportes(Environment.MachineName, param));