経由でディスパッチされたスレッドの 1 つから UI を更新しようとしていますTask.Factory
。UI を適切に更新するのに苦労しています。
私が観察している動作は次のとおりです。
Task.Factory.StartNew(() =>
{
// UI does get updated from here.
}).ContinueWith(task =>
{
// UI does *not* get updated from here.
});
でディスパッチされたスレッド内で UI を更新する適切な方法は何Task Factory
ですか?
参照用の実際のコードは次のとおりです。
private string CurrentProcess
{
set { _eventAggregator.GetEvent<CurrentProcessUpdatedEvent>().Publish(value); }
}
private double ProgressPercentage
{
set
{
_eventAggregator.GetEvent<ProgressPercentageUpdatedEvent>()
.Publish(Utilities.GetProgressPercentage(value));
}
}
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
var tasks = new List<Task<DataTable>>();
string siteCollectionUrl;
string connectionString;
try
{
Dictionary<string, object> session = ApplicationContext.Current.Session;
try
{
if ((double) session["ProgressPercentage"] > 0) return;
}
catch
{
}
siteCollectionUrl = (string) session["SiteCollection"];
connectionString = (string) session["Database"];
}
catch
{
return;
}
_eventAggregator.GetEvent<IsProcessingChangedEvent>().Publish(true);
CurrentProcess = "Loading resources.";
Task<DataTable> spTask = Task<DataTable>.Factory.StartNew(() =>
{
using (ChannelFactory<ISharePointService> service = Utilities.GetSharePointService())
{
ISharePointService sharePointService = service.CreateChannel();
DataTable spDatatable = sharePointService.GetResources(siteCollectionUrl);
Task.Factory.StartNew(() => { ProgressPercentage = 10; }, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
return spDatatable;
}
});
tasks.Add(spTask);
Task<DataTable> buildTableTask = Task<DataTable>.Factory.ContinueWhenAll(tasks.ToArray(), t =>
{
DataTable spDatatable = t[0].Result;
double percent = 10/spDatatable.Rows.Count;
var columnMap = new Dictionary<string, string>
{
{"IsValid", null},
{"Reason", null},
{"SPID", "ID"},
{"DBID", "EXTID"},
{"Name", "Title"},
{"Account", "SharePointAccount"},
{"Email", "Email"},
{"Generic", "Generic"},
{"Department", "Department"},
{"TempDept", "TempDept"},
{"Role", "Role"},
{"TempRole", "TempRole"},
{"HolidaySchedule", "HolidaySchedule"},
{"WorkHours", "WorkHours"}
};
DataTable spResources = BuildDataTable(columnMap);
foreach (DataRow dataRow in spDatatable.Rows)
{
DataRow row = spResources.NewRow();
foreach (var pair in columnMap)
{
try
{
row[pair.Key] = dataRow[pair.Value];
}
catch
{
}
}
spResources.Rows.Add(row);
Task.Factory.StartNew(() => { ProgressPercentage = percent; }, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
}
return spResources;
});
tasks.Add(buildTableTask);
Task<DataTable> dbTask = Task<DataTable>.Factory.StartNew(() =>
{
using (var sqlConnection = new SqlConnection(connectionString))
{
using (var sqlCommand = new SqlCommand(SQL, sqlConnection))
{
sqlConnection.Open();
using (SqlDataReader sqlDataReader = sqlCommand.ExecuteReader())
{
var dataTable = new DataTable();
dataTable.Load(sqlDataReader);
Task.Factory.StartNew(() => { ProgressPercentage = 10; }, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
return dataTable;
}
}
}
});
tasks.Add(dbTask);
Task.Factory.ContinueWhenAll(tasks.ToArray(), t =>
{
DatabaseResources = t[2].Result;
DataTable sharePointResources = t[1].Result;
if (sharePointResources != null)
{
int resourceIndex = 1;
int totalResources = sharePointResources.Rows.Count;
double percentPoint = 70/totalResources;
foreach (DataRow row in sharePointResources.Rows)
{
DataRow currentRow = row;
Task.Factory.StartNew(() =>
{
CurrentProcess = string.Format("[{0}/{1}] Processing: {2}",
resourceIndex++, totalResources,
currentRow["Name"]);
}, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
bool isValid = true;
var reasons = new List<string>();
DataRow[] dataRows =
_databaseResources.Select(string.Format("ResourceID = {0}", row["DBID"]));
if (dataRows.Any())
{
DataRow dataRow = dataRows[0];
string tempDept = (row["TempDept"] ?? string.Empty).ToString();
string dept = (row["Department"] ?? string.Empty).ToString();
string tempRole = (row["TempRole"] ?? string.Empty).ToString();
string role = (row["Role"] ?? string.Empty).ToString();
string hs = (row["HolidaySchedule"] ?? string.Empty).ToString();
string dbhs = (dataRow["HolidaySchedule"] ?? string.Empty).ToString();
string wh = (row["WorkHours"] ?? string.Empty).ToString();
string dbwh = (dataRow["WorkHours"] ?? string.Empty).ToString();
if (string.IsNullOrEmpty(dept))
{
if (!dept.Equals(tempDept))
{
isValid = false;
reasons.Add("Department does not match Temp Dept");
}
}
if (string.IsNullOrEmpty(role))
{
if (!role.Equals(tempRole))
{
isValid = false;
reasons.Add("Role does not match Temp Role");
}
}
if (string.IsNullOrEmpty(hs))
{
if (!hs.Equals(dbhs))
{
isValid = false;
reasons.Add("Holiday Schedule does not match Holiday Schedule from database");
}
}
if (string.IsNullOrEmpty(wh))
{
if (!wh.Equals(dbwh))
{
isValid = false;
reasons.Add("Work Hours does not match Work Hours from database");
}
}
}
else
{
isValid = false;
reasons.Add("Resource does not exist in database");
}
row["IsValid"] = isValid;
row["Reason"] = string.Join("\n", reasons.ToArray());
Task.Factory.StartNew(() => { ProgressPercentage = percentPoint; }, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
}
SharePointResources = sharePointResources;
}
_eventAggregator.GetEvent<ProgressPercentageUpdatedEvent>()
.Publish(Utilities.ResetProgressPercentage());
_eventAggregator.GetEvent<IsProcessingChangedEvent>().Publish(false);
});