Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从任务返回而不阻塞UI线程_C#_Wpf_Multithreading_Task - Fatal编程技术网

C# 从任务返回而不阻塞UI线程

C# 从任务返回而不阻塞UI线程,c#,wpf,multithreading,task,C#,Wpf,Multithreading,Task,我有一个返回数据表的方法。我需要所有的sql东西在一个线程中运行,然后能够传回一个datatable,而不会阻塞UI线程。据我所知,当您调用Task.Result时,它会阻塞UI线程,直到任务完成。我该怎么解决这个问题呢。我读过关于使用wait和async的文章,但我还没有完全弄清楚如何在任务中使用它 public static DataTable LaunchLocationMasterListReport(ObservableCollection<string> BuiltCon

我有一个返回数据表的方法。我需要所有的sql东西在一个线程中运行,然后能够传回一个datatable,而不会阻塞UI线程。据我所知,当您调用Task.Result时,它会阻塞UI线程,直到任务完成。我该怎么解决这个问题呢。我读过关于使用wait和async的文章,但我还没有完全弄清楚如何在任务中使用它

public static DataTable LaunchLocationMasterListReport(ObservableCollection<string> BuiltConditionsList, ObservableCollection<string> BuiltSortList, ObservableCollection<ListBoxCheckBoxItemModel> ColumnsForReport,
    bool LocationNotesCheckBox, ref string reportQuery, ref string reportQueryforSave, ref string reportView, ref string queryCondtions)
{
    queryCondtions = BuildConditionAndSorts(queryCondtions, BuiltConditionsList, BuiltSortList);
    reportQueryforSave = "SELECT * FROM LocationMasterReportView";
    reportView = "LocationMasterReportView";
    reportQuery = "SELECT * FROM LocationMasterReportView " + queryCondtions;

    return LaunchReport(reportQuery, ColumnsForReport).Result;
}

async private static Task<DataTable> LaunchReport(string reportQuery, ObservableCollection<ListBoxCheckBoxItemModel> ColumnsForReport)
{
    SqlConnection myConn = new SqlConnection(Settings.Default.UltrapartnerDBConnectionString);
    DataTable dt = new DataTable();

    string rq = reportQuery;

    Task<DataTable> task = Task.Factory.StartNew(() =>
    {
        using (SqlCommand comm = new SqlCommand(rq, myConn))
        {
            myConn.Open();
            dt.Load(comm.ExecuteReader());
            myConn.Close();
        }

        if (dt.Rows.Count == 0)
        {
            MessageBox.Show("Contains No Results");
            return null;
        }

        foreach (ListBoxCheckBoxItemModel lbc in ColumnsForReport)
        {
            if (!lbc.IsSelected)
            {
                dt.Columns.Remove(lbc.Name.ToString());
            }
        }

        return dt;

    }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);

    return await task;
}
公共静态数据表LaunchLocationMasterListReport(ObservableCollection内置条件列表、ObservableCollection内置条件列表、ObservableCollection列报告、,
bool LocationNotesCheckBox、ref string reportQuery、ref string reportQueryforSave、ref string reportView、ref string queryconditions)
{
QueryConditions=BuildConditions和Sorts(QueryConditions,BuiltConditionsList,BuiltSortList);
reportQueryforSave=“从LocationMasterReportView中选择*”;
reportView=“LocationMasterReportView”;
reportQuery=“从LocationMasterReportView中选择*”+查询条件;
返回LaunchReport(reportQuery,ColumnsForReport);
}
异步专用静态任务启动报告(字符串报告查询、ObservableCollection列报告)
{
SqlConnection myConn=新的SqlConnection(Settings.Default.UltrapartnerDBConnectionString);
DataTable dt=新的DataTable();
字符串rq=reportQuery;
Task Task=Task.Factory.StartNew(()=>
{
使用(SqlCommand comm=newsqlcommand(rq,myConn))
{
myConn.Open();
dt.Load(comm.ExecuteReader());
myConn.Close();
}
如果(dt.Rows.Count==0)
{
Show(“不包含任何结果”);
返回null;
}
foreach(列ForReport中的ListBoxCheckBoxItemModel lbc)
{
如果(!lbc.IsSelected)
{
Remove(lbc.Name.ToString());
}
}
返回dt;
},CancellationToken.None,TaskCreationOptions.LongRunning,TaskScheduler.Default);
返回等待任务;
}

我同意在这里使用async/await是最好的方法。如前所述,当您等待异步方法时,即使声明的返回类型是任务,编译器也会将其转换为隐式返回类型T

问题是所有异步方法都必须返回void、Task或Task。因此,一旦开始使用它们,就必须“冒泡”使用“async”方法属性,直到到达一个点,在这个点上,您可以阻塞结果,或者您的方法可以是void或Task(即,您已经使用了实际结果)

请参见这个简单的基于UI的示例:

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        statusText.Text = "Running";
        statusText.Text = await _ComputeText(true);
        statusText.Text = await _ComputeText(false);
    }

    private static async Task<string> _ComputeText(bool initialTask)
    {
        string result = await Task.Run(() =>
            {
                Thread.Sleep(2000);
                return initialTask ? "Task is done!" : "Idle";
            });

        return result;
    }
}
//
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
专用异步无效按钮\u单击(对象发送方,路由目标)
{
statusText.Text=“正在运行”;
statusText.Text=wait_ComputeText(true);
statusText.Text=wait_ComputeText(false);
}
专用静态异步任务\u ComputeText(bool initialTask)
{
字符串结果=等待任务。运行(()=>
{
《睡眠》(2000年);
返回initialTask?“任务已完成!”:“空闲”;
});
返回结果;
}
}
请注意,按钮事件处理程序“button_Click”仅声明为“void”返回。但我可以这样做,因为我在该方法中使用异步结果

在您的情况下,在异步任务完成之前,返回的DataTable不可用。因此,您必须将每个方法声明为“async”,直到方法实际使用DataTable时为止。即使在那里,该方法也需要声明为async,但您不会返回DataTable,因此该方法的返回类型可以是“void”或“Task”。一个常见的场景是,该方法是一个UI事件处理程序,因此“void”应该可以(并且在事件处理程序委托中需要使用);你的代码无论如何都不会调用它。但从技术上讲,使用“任务”更为正确,因此,如果在您的上下文中它起作用,您应该这样做


如果没有一个简洁而完整的示例,就很难提供比这更具体的内容。

在任务中使用
async
wait
非常简单:将
async
添加到方法签名中,将返回类型更改为
task
,并将
返回任务.Result
替换为
return task
。您可能需要将调用此方法的代码重构为
async
,以便
wait
结果(这将为您提供
DataTable
而不是任务)。阅读更多关于这个主题的内容——这绝对值得。不要使用
task.Result
。这是一个阻塞呼叫。使用
返回等待任务
。(顺便说一句:您的方法签名类似于此
async public Task Launch
)我必须使用。结果如何获取
DataTable
,对吗?让我用我所拥有的更新代码。感谢您的详细解释…这确实有助于理解此.net 4没有任务。运行有解决方案吗?@blackholeearth0\u gmail:有了.net 4,您可以作为一个单独的库。或者,您可以在.NET 4中使用
TaskFactory.StartNew()
,但在这种情况下,您必须编写自己的延续代码(即调用
ContinueWith()
),而不能利用async/Wait。