从OnCreate Overriden方法启动异步方法的问题

时间:2017-08-08 15:34:50

标签: c# multithreading asynchronous xamarin

       Within OnCreate()
       new Thread(new ThreadStart(() => {
            this.RunOnUiThread(async () =>
            {
                await SetData(TodaysDate); ;
                //await FindNotesForDay(TodaysDate, TodaysDate.AddDays(+6));
                progress.Dismiss();
            });
        })).Start();



        private async Task SetData(DateTime date)
    {
        await Task.Run(() =>
        {
            dicMyMap = null;

            dicMyMap = new Dictionary<string, List<ClassInstance>>();

            List<string> group = new List<string>();

            group.Add("Monday");
            group.Add("Tuesday");
            group.Add("Wednesday");
            group.Add("Thursday");
            group.Add("Friday");

            dicMyMap.Add(group[0], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));

            date = date.AddDays(+1);

            dicMyMap.Add(group[1], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));

            date = date.AddDays(+1);

            dicMyMap.Add(group[2], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));

            date = date.AddDays(+1);

            dicMyMap.Add(group[3], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));

            date = date.AddDays(+1);

            dicMyMap.Add(group[4], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));


            myAdapater = new ExpandableListViewAdapter(this, group, dicMyMap);

            expandableListView.SetAdapter(myAdapater);
        });
    }

    private List<ClassInstance> ListsPopulation(String date)
    {
        string sql = "SELECT * FROM lectures join groupConvert using (Groups) where StartDate = '" + date + "' AND Cohort = '" + User.Cohort + "' AND Year = '" + User.IntakeYear + "';";

        List<ClassInstance> Temp = new List<ClassInstance>();

        //Insert Header
        Temp.Add(new ClassInstance("Start Time", "End   Time", "Subject", "Location", "", ""));

        using (MySqlCommand cmd = new MySqlCommand(sql, Connect.GetConnection()))
        {
             MySqlDataReader reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                ClassInstance c = new ClassInstance(reader["StartTime"].ToString(), reader["EndTime"].ToString(), reader["Theme"].ToString(), reader["Location"].ToString(), reader["Essential"].ToString(), reader["Notes"].ToString());
                Temp.Add(c);
            }
        }

        if (Temp.Count == 1)
        {
            Temp.Clear();
            Temp.Add(new ClassInstance("No Classes", "", "", "", "", ""));
        }


        return Temp;
    }

你好

我目前正在尝试从AWS上托管的数据库填充ListView。您可以想象加载需要一些时间。我的问题是我当前的代码抛出错误。抛出的错误是模棱两可的,只是表明程序崩溃了。

本质上我想做的很简单,我基本上只想在加载这些方法时显示一个对话框。

关于我的代码的任何建议都会非常好。

编辑:我已将错误消息缩小到代码的这个区域。在尝试使用线程之前,我能够加载此Activity,但是由于没有加载消息,用户看起来活动已经冻结而不是它正在加载的事实。

谢谢, 乔

1 个答案:

答案 0 :(得分:0)

所以我设法修复上面的代码以正确运行。

如果您有任何反馈或意见,请告诉我,我希望有人认为这有帮助。

我完全错误地使用了Async方法,你也无法从oncreate调用Async方法,因为我确定你知道。我的解决方案的一部分是更改我使Async错误地返回void的所有方法(意味着它们是同步的)。

然后我创建了一个运行命令的线程,现在它们最终以正确的顺序运行:)。

在Thread中需要注意的是,受UI影响的任何元素都需要使用主UI线程运行它们,这也适用于它们调用的方法。

以下是为解决我遇到的问题而创建的代码区域

    // Try catch attempt to catch all errors, the error dialog thrown within 
    //the catch is fairly simple 
    try
        {
            //Start loading spinner
            var LoadingProgressDialog = ProgressDialog.Show(this, "Loading", "Loading", false);

            //Start loading thread, this thread will carry out the functions 
            // in the order you requested
            Thread LoadingThread = new Thread(() =>
            {
                //Line below only relevant to my code
                StartMonday.Text = "Week Commencing On " + TodaysDate.ToLongDateString();
                // Call this method first
                SetData(TodaysDate);
                // call this method second
                FindNotesForWeek(TodaysDate, 7);
                //Update the UI on the main thread but call third this will close the loading dialog message
                RunOnUiThread(() => LoadingProgressDialog.Hide());
            // End of thread
            });
            //Run the thread
            LoadingThread.Start();
        }
        catch (Exception e)
        {
            var ErrorMessageDialog = ProgressDialog.Show(this, "Loading", e.ToString(), false);
        }

以下是我的完整课程,供其他用户参考。我没有在此评论中将此代码描述为足够大

        namespace MedicalHubApplication
        {
        [Activity(Label = "TimeTable", NoHistory = true)]
        public class TimeTable : Activity
        {
       ClassInstance populateClass = new ClassInstance();
       UserInstance User = new UserInstance();
       GetConnectionClass Connect = new GetConnectionClass();
       Dictionary<string, List<ClassInstance>> dicMyMap;

    TextView DateHeaderTV;
    TextView NoteHeaderTV;

    ExpandableListViewAdapter myAdapater;
    ExpandableListView expandableListView;

    // Need Instance of List 
    NotesListViewAdapter myNoteAdapater;
    ListView NotesListView;
    ScrollView ScrollViewList;

    TextView StartMonday;
    Button SelectDateButton;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        // Create your application here
        SetContentView(Resource.Layout.TimeTable);

        expandableListView = FindViewById<ExpandableListView>(Resource.Id.ListViewExpanded);
        StartMonday = FindViewById<TextView>(Resource.Id.TextViewStartDateMonday);
        SelectDateButton = FindViewById<Button>(Resource.Id.SelectDateButton);
        NotesListView = FindViewById<ListView>(Resource.Id.NotesListView);
        DateHeaderTV = FindViewById<TextView>(Resource.Id.DateHeader);
        NoteHeaderTV = FindViewById<TextView>(Resource.Id.NoteHeader);
        ScrollViewList = FindViewById<ScrollView>(Resource.Id.ScrollView);

        // Populate User 
        User = JsonConvert.DeserializeObject<UserInstance>(Intent.GetStringExtra("User"));

        //Find Monday 
        DateTime TodaysDate = DateTime.Now;
        while (TodaysDate.DayOfWeek != DayOfWeek.Monday) TodaysDate = TodaysDate.AddDays(-1);

        try
        {
            var LoadingProgressDialog = ProgressDialog.Show(this, "Loading", "Loading", false);

            Thread LoadingThread = new Thread(() =>
            {
                StartMonday.Text = "Week Commencing On " + TodaysDate.ToLongDateString();
                SetData(TodaysDate);
                FindNotesForWeek(TodaysDate, 7);
                RunOnUiThread(() => LoadingProgressDialog.Hide());

            });

            LoadingThread.Start();
        }
        catch (Exception e)
        {
            var ErrorMessageDialog = ProgressDialog.Show(this, "Loading", e.ToString(), false);
        }

        SelectDateButton.Click += delegate
        {
            DateSelectOnClick();  
        }; 
    }

    private void DateSelectOnClick()
    {
        DatePickerFragment frag = DatePickerFragment.NewInstance(delegate (DateTime SelectedDate)
        {
            while (SelectedDate.DayOfWeek != DayOfWeek.Monday) SelectedDate = SelectedDate.AddDays(-1);

            try
            {
                var LoadingProgressDialog = ProgressDialog.Show(this, "Loading", "Loading", false);

                Thread LoadingThread = new Thread(() =>
                {
                    RunOnUiThread(() => StartMonday.Text = "Week Commencing On " + SelectedDate.ToLongDateString());
                    SetData(SelectedDate);
                    FindNotesForWeek(SelectedDate, 7);
                    RunOnUiThread(() => LoadingProgressDialog.Hide());

                });

                LoadingThread.Start();
            }
            catch (Exception e)
            {
                var ErrorMessageDialog = ProgressDialog.Show(this, "Loading", e.ToString(), false);
            }
        });
        frag.Show(FragmentManager, DatePickerFragment.TAG);
    }

    private void SetData(DateTime date)
    {

        dicMyMap = null;

        dicMyMap = new Dictionary<string, List<ClassInstance>>();

        List<string> group = new List<string>();

        group.Add("Monday");
        group.Add("Tuesday");
        group.Add("Wednesday");
        group.Add("Thursday");
        group.Add("Friday");

        dicMyMap.Add(group[0], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));

        date = date.AddDays(+1);

        dicMyMap.Add(group[1], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));

        date = date.AddDays(+1);

        dicMyMap.Add(group[2], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));

        date = date.AddDays(+1);

        dicMyMap.Add(group[3], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));

        date = date.AddDays(+1);

        dicMyMap.Add(group[4], ListsPopulation(date.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)));


        myAdapater = new ExpandableListViewAdapter(this, group, dicMyMap);

        RunOnUiThread(() => expandableListView.SetAdapter(myAdapater));

    }

    private List<ClassInstance> ListsPopulation(String date)
    {
        string sql = "SELECT * FROM lectures join groupConvert using (Groups) where StartDate = '" + date + "' AND Cohort = '" + User.Cohort + "' AND Year = '" + User.IntakeYear + "';";

        List<ClassInstance> Temp = new List<ClassInstance>();

        //Insert Header
        Temp.Add(new ClassInstance("Start Time", "End   Time", "Subject", "Location", "", ""));

        using (MySqlCommand cmd = new MySqlCommand(sql, Connect.GetConnection()))
        {
             MySqlDataReader reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                ClassInstance c = new ClassInstance(reader["StartTime"].ToString(), reader["EndTime"].ToString(), reader["Theme"].ToString(), reader["Location"].ToString(), reader["Essential"].ToString(), reader["Notes"].ToString());
                Temp.Add(c);
            }
        }

        if (Temp.Count == 1)
        {
            Temp.Clear();
            Temp.Add(new ClassInstance("No Classes", "", "", "", "", ""));
        }


        return Temp;
    }

    private void FindNotesForWeek(DateTime StartDate, int DaysInMonth)
    {
        List<NotesInstance> WeekNotes = new List<NotesInstance>();

        WeekNotes.AddRange(FindNotesForDay(StartDate, StartDate.AddDays(+DaysInMonth)));

        if (WeekNotes.Count != 0)
        {
            RunOnUiThread(() => NoteHeaderTV.Visibility = ViewStates.Visible);
            RunOnUiThread(() => NotesListView.Visibility = ViewStates.Visible);
            RunOnUiThread(() => DateHeaderTV.Text = "Date:");

            myNoteAdapater = new NotesListViewAdapter(this, WeekNotes);

            RunOnUiThread(() => NotesListView.Adapter = myNoteAdapater);
        }
        else
        {
            RunOnUiThread(() => NoteHeaderTV.Visibility = ViewStates.Invisible);
            RunOnUiThread(() => NotesListView.Visibility = ViewStates.Invisible);
            RunOnUiThread(() => DateHeaderTV.Text = "No Notifications");
        }

        // Set up Adapter 
        myNoteAdapater = new NotesListViewAdapter(this, WeekNotes);

        RunOnUiThread(() => NotesListView.Adapter = myNoteAdapater);
    }

    private List<NotesInstance> FindNotesForDay(DateTime StartDate, DateTime EndDate)
    {
        string sql = "SELECT *  FROM Notes WHERE dates between '" + StartDate.ToString("yyyy-MM-dd") + "' AND '" + EndDate.ToString("yyyy-MM-dd") + "' AND yearGroup = '" + User.IntakeYear.ToString() + "';";

        List<NotesInstance> Temp = new List<NotesInstance>();

        using (MySqlCommand cmd = new MySqlCommand(sql, Connect.GetConnection()))
        {

            MySqlDataReader reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                NotesInstance c = new NotesInstance(reader.GetDateTime("dates").ToString("dd-MM-yyyy"), reader["Notes"].ToString());
                Temp.Add(c);
            }
        }

        return Temp;
    }
}

}