Ehsan Akbar Ehsan Akbar - 2 months ago 30
C# Question

start thread returns System.InvalidOperationException: The current SynchronizationContext may not be used as a TaskScheduler

I add a dashboard

devexpress
that run a
storeprocedure
and it takes a long time.So i create a simple thread in my application in
form_load


public void LoadDashboard()
{
using (Stream s = new MemoryStream(Encoding.Default.GetBytes(Resource.Dashboard.MaterialDashboard1)))
{
s.Position = 0;
dashboardViewer1.LoadDashboard(s);
}
}

private void frmMaterialDashboard_Load(object sender, EventArgs e)
{
Thread newth=new Thread(LoadDashboard);
newth.Start();
int UserId = int.Parse(Configuration.AccountDetail.UserId.ToString());
lblUserName.Caption = _userRepository.Get().Where(i => i.Id == UserId).First().FullName;
alertControl1.Show(this, "Welcome","Welcome to SPMS Mr."+_userRepository.FindById(Configuration.AccountDetail.UserId).First().FullName +"\n Server time:"+DateTime.Now);
}


But when i run my application i get this error :

An unhandled exception of type 'DevExpress.DashboardCommon.DashboardInternalException' occurred in DevExpress.Dashboard.v15.2.Win.dll

Additional information: Internal error. Please contact the application vendor or your system administrator and provide the following information.



System.InvalidOperationException: The current SynchronizationContext may not be used as a TaskScheduler.

at System.Threading.Tasks.SynchronizationContextTaskScheduler..ctor()

at DevExpress.DashboardWin.Native.WinDashboardService.RequestCustomizationServices(RequestCustomizationServicesEventArgs e)

at DevExpress.DashboardCommon.Service.DashboardService.DevExpress.DashboardCommon.Service.IDashboardServiceAdminHandlers.OnRequestCustomizationServices(Object sender, RequestCustomizationServicesEventArgs e)

at DevExpress.DashboardCommon.Server.DashboardSession.CreateDataLoaderParameters(ReloadDataArgs args)

at DevExpress.DashboardCommon.Server.DashboardSession.CreateDataLoader(ReloadDataArgs args)

at DevExpress.DashboardCommon.Server.DashboardSession.LoadData(IEnumerable`1 dataSourceComponentNames, ReloadDataArgs args)

at DevExpress.DashboardCommon.Server.DashboardSession.ReloadData(IEnumerable`1 dataSourceComponentNames, ReloadDataArgs args)

at DevExpress.DashboardCommon.Server.DashboardSession.Initialize(DashboardSessionState state, Boolean isDesignMode)

at DevExpress.DashboardCommon.Service.DashboardServiceOperation`1.Execute(DashboardServiceResult result)


Updated
I change my code like this ,It works without any error and the data is shown but without any async operation and i have to wait to load data

public async Task<Stream> LoadDashboard()
{

Stream s = new MemoryStream(Encoding.Default.GetBytes(Resource.Dashboard));
s.Position = 0;
return s;

}
private async void frmMaterialDashboard_Load(object sender, EventArgs e)
{
Stream dashboardData = await LoadDashboard();
dashboardViewer1.LoadDashboard(dashboardData);


int UserId = int.Parse(Configuration.AccountDetail.UserId.ToString());
lblUserName.Caption = _userRepository.Get().Where(i => i.Id == UserId).First().FullName;
alertControl1.Show(this, "Welcome","Welcome to SPMS Mr."+_userRepository.FindById(Configuration.AccountDetail.UserId).First().FullName +"\n Server time:"+DateTime.Now);

}

Answer

Without full context of the problem I can't give you an exact solution, but overall, you cannot access UI elements from another thread. That means you need to do all request and computation on another thread, and then update UI elements on UI thread. Consider such simplified solution that does not explicitly start a new thread:

// event on UI thread    
private async void frmMaterialDashboard_Load(object sender, EventArgs e)
{
    var dashboardData = await LoadDashboardDataFromDatabaseAsync();
    dashboardViewer1.Load(dashboardData);
}

public async Task<DashboardData> LoadDashboardDataFromDatabaseAsync()
{
    string query = "...";
    var queryResult = await db.ExucuteQueryAsync(query).ConfigureAwait(false);
    return ConvertQueryRequltToDashboardData(queryResult);
}
Comments