问题
I'm using the busyIndicator in my program that works with MVVM pattern, I found out that there is a problem with background worker and dealing with objects that are binded in the view so I used the Dispacher.Invoke method on all of the functions that use binded properties, after I used the Dispacher the busyIndicator showed up, but when the backgoundWorker finished my view had no elements inside, what am I doing wrong?
I know it's a little low in code but i didn't know what (and if) will help, if necessary please let me know and I'll edit this message with the desired code.
EDIT:
Here is some code that might help:
This is the creation of the BW, it happens on the viewModel constructor
bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync(false);
This is the BW functions
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.IsBusy = false;
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
this.BusyContent = "Please Wait...";
this.IsBusy = true;
ShowSystem((bool)e.Argument);
}
The method showSystem is very long so I'll add just the part that using UI elemnts
List<NodeViewModel> nodes = null;
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => nodes = new List<NodeViewModel>()));
int width = 0;
int height = 0;
foreach (var system in MainNet.Systems)
{
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => nodes.Add(CreateNode(system.Name, new Point(width, height), false, system.InputNum, system.OutputNum, system.Interfaces, system.Enums, system.Structs, update))));
width += 150;
if (width >= 700)
{
width = 0;
height += 100;
}
}
if (MainWindow.IsFlow)
{
Object[] getInterfacesWithGuidToFlowParam = new Object[1];
getInterfacesWithGuidToFlowParam[0] = MainWindow.GuidToFlow;
interfacesForFlow = (List<String>)getInterfacesWithGuidToFlow.Invoke(sqlDB, getInterfacesWithGuidToFlowParam);
}
foreach (var system in MainNet.Systems)
{
if (system.OutputNum > 0) //this system has an output connector
{
int i = 0;
foreach (var outId in system.Outputs) //loop throw all systems ids that current system is connected to
{;
ConnectionViewModel connection = null;
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection = new ConnectionViewModel()));
Object[] getSystemNameParams = new Object[1];
getSystemNameParams[0] = outId;
string destSystemName = "";
destSystemName = (String)getSystemName.Invoke(sqlDB, getSystemNameParams);
NodeViewModel sourceItem = null;
NodeViewModel destItem = null;
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => sourceItem = nodes.Find(x => x.Name == system.Name)));
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => destItem = nodes.Find(x => x.Name == destSystemName)));
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => destItem.InputSystems.Add(sourceItem.Name)));
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => sourceItem.OutputSystems.Add(destItem.Name)));
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.SourceConnector = sourceItem.OutputConnectors[i++]));
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.DestConnector = destItem.InputConnectors[destItem.InputConnectors.Count - 1]));
// Add the connection to the view-model.
//
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.Type = ConnectionViewModel.ConnectorType.REGULAR));
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => this.Network.Connections.Add(connection)));
if (MainWindow.IsFlow)
{
foreach (var @interface in interfacesForFlow)
{
String[] systems = @interface.Split('_');
if(systems[0].Equals(sourceItem.Name) && systems[1].Equals(destItem.Name))
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => connection.Type = ConnectionViewModel.ConnectorType.FLOW));
}
}
}
}
}
Edit:
This is the part of getting the data from Database:
MainNet = Common.Model.Network.getNetwork();
Debug.WriteLine("MainNet.Systems.Count = " + MainNet.Systems.Count);
if (MainNet.Systems.Count == 0)
update = true;
List<String> systemNames = new List<string>();
if (update)
{
if(MainNet.Systems.Count > 0)
MainNet.Systems.Clear();
if (this.Network.Nodes.Count > 0)
{
this.Network.Nodes.Clear();
this.Network.Connections.Clear();
}
try
{
systemNames = (List<String>)getAllSystemMethod.Invoke(sqlDB, null);
Debug.WriteLine("Success getAllSystemMethod");
}
catch (Exception ex)
{
logger.addMessage("Error in getAllSystemMethod: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getAllSystemMethod: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
#region CreateSystems
foreach (var sysName in systemNames)
{
#region Intializating
ObservableCollection<Common.Model.Enum> enums = new ObservableCollection<Common.Model.Enum>();
ObservableCollection<Common.Model.Struct> structs = new ObservableCollection<Common.Model.Struct>();
ObservableCollection<Common.Model.Interface> interfaces = new ObservableCollection<Common.Model.Interface>();
//List<Model.Enum> enums = new List<Model.Enum>();
//List<Model.Struct> structs = new List<Model.Struct>();
//List<Model.Interface> interfaces = new List<Model.Interface>();
int systemId = -1;
Object[] getSystemIdParams = new Object[1];
getSystemIdParams[0] = sysName;
try
{
systemId = (int)getSystemId.Invoke(sqlDB, getSystemIdParams);
Debug.WriteLine("Success getSystemId systemId = " + systemId);
}
catch (Exception ex)
{
logger.addMessage("Error in getSystemId: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getSystemId: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
List<int> sysEnumsIds = new List<int>();
List<int> sysStructsIds = new List<int>();
List<int> sysInterfacesIds = new List<int>();
Object[] getSysEnumsIdParams = new Object[1];
getSysEnumsIdParams[0] = systemId;
try
{
sysEnumsIds = (List<int>)getSysEnumsId.Invoke(sqlDB, getSysEnumsIdParams); //return List<int> all system Enums ids
if (sysEnumsIds.Count > 0)
Debug.WriteLine("Success getSysEnumsId first count is " + sysEnumsIds.Count);
else
Debug.WriteLine("success getSysEnumsId but no ids found");
}
catch (Exception ex)
{
logger.addMessage("Error in getSysEnumsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getSysEnumsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
Object[] getSysStructsIdParams = new Object[1];
getSysStructsIdParams[0] = systemId;
try
{
sysStructsIds = (List<int>)getSysStructsId.Invoke(sqlDB, getSysStructsIdParams);
if (sysStructsIds.Count > 0)
Debug.WriteLine("success getSysStructsId count = " + sysStructsIds.Count);
else
Debug.WriteLine("success getSysStructsId but no ids found");
}
catch (Exception ex)
{
logger.addMessage("Error in getSysStructsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getSysStructsId: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
Object[] getSysInterfacesIdParams = new Object[1];
getSysInterfacesIdParams[0] = systemId;
try
{
sysInterfacesIds = (List<int>)getSysInterfacesId.Invoke(sqlDB, getSysInterfacesIdParams);
if (sysInterfacesIds.Count > 0)
Debug.WriteLine("Success getSysInterfacesId count = " + sysInterfacesIds.Count);
else
Debug.WriteLine("success getSysInterfacesId but no ids found");
}
catch (Exception ex)
{
logger.addMessage("Error in getSysInterfacesId: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getSysInterfacesId: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
#endregion
Object[] getStructFromIdParam = new Object[1];
getStructFromIdParam[0] = @struct;
List<Object> tempStruct = new List<object>();
try
{
tempStruct = (List<Object>)getStructFromId.Invoke(sqlDB, getStructFromIdParam);
Debug.WriteLine("Success getStructFromId " + tempStruct.Count);
}
catch (Exception ex)
{
logger.addMessage("Error in getStructFromIdParam : " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getStructFromIdParam : " + ex.Message + " Inner: " + ex.InnerException.Message);
}
structs.Add(new Common.Model.Struct(Convert.ToString(tempStruct[0]), Convert.ToString(tempStruct[1]), Convert.ToString(tempStruct[2]), fields, bitFields));
Debug.WriteLine("Success adding new struct: " + structs.Last().Name);
}
#endregion
#region GetInterfaces
foreach (var @interface in sysInterfacesIds) //get interface
{
ObservableCollection<Common.Model.Message> messages = new ObservableCollection<Common.Model.Message>();
ObservableCollection<Common.Model.Definition> definitions = new ObservableCollection<Common.Model.Definition>();
ObservableCollection<Common.Model.Include> includes = new ObservableCollection<Common.Model.Include>();
List<int> includesIds = new List<int>();
List<int> definitionsIds = new List<int>();
List<int> messagesIds = new List<int>();
#region getIncludes
Object[] getIncludesIdsParams = new object[1];
getIncludesIdsParams[0] = @interface;
try
{
includesIds = (List<int>)getIncludesIds.Invoke(sqlDB, getIncludesIdsParams);
Debug.WriteLine("Success getIncludesIds " + includesIds.Count);
}
catch (Exception ex)
{
logger.addMessage("Error in getIncludesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getIncludesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
foreach (var id in includesIds)
{
Object[] getIncludeParams = new object[1];
getIncludeParams[0] = id;
string includeName = "";
try
{
includeName = (string)getInclude.Invoke(sqlDB, getIncludeParams);
Debug.WriteLine("Success get include name = " + includeName);
}
catch (Exception ex)
{
logger.addMessage("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
}
includes.Add(new Common.Model.Include(includeName));
}
#endregion
#region getdefinitions
Object[] getdefinitionsIdsParams = new object[1];
getdefinitionsIdsParams[0] = @interface;
try
{
definitionsIds = (List<int>)getDefinitionsIds.Invoke(sqlDB, getdefinitionsIdsParams);
Debug.WriteLine("Success getDefinitionsIds " + definitionsIds.Count);
}
catch (Exception ex)
{
logger.addMessage("Error in getDefinitionsIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getDefinitionsIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
foreach (var id in definitionsIds)
{
List<Object> definition = new List<object>();
Object[] getDefinitionParams = new object[1];
getDefinitionParams[0] = id;
string includeName = "";
try
{
definition = (List<Object>)getDefinition.Invoke(sqlDB, getDefinitionParams);
Debug.WriteLine("Success getDefinisions " + definition[0]);
}
catch (Exception ex)
{
logger.addMessage("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getInclude " + ex.Message + " Inner: " + ex.InnerException.Message);
}
definitions.Add(new Common.Model.Definition(Convert.ToString(definition[0]), Convert.ToInt32(definition[1])));
}
#endregion
#region getMessages
Object[] getMessagesIdsParams = new object[1];
getMessagesIdsParams[0] = @interface;
Debug.WriteLine("Trying to get messages for interface #" + @interface);
try
{
messagesIds = (List<int>)getMessagesIds.Invoke(sqlDB, getMessagesIdsParams);
Debug.WriteLine("Success getMessagesIds " + messagesIds.Count);
}
catch (Exception ex)
{
logger.addMessage("Error in getMessagesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getMessagesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
foreach (var id in messagesIds)
{
//List<Model.MType> types = new List<Model.MType>();
ObservableCollection<Common.Model.MType> types = new ObservableCollection<Common.Model.MType>();
List<int> typesIds = new List<int>();
Object[] getMessageTypesIdsParams = new Object[1];
getMessageTypesIdsParams[0] = id;
try
{
typesIds = (List<int>)getMessageTypesIds.Invoke(sqlDB, getMessageTypesIdsParams);
Debug.WriteLine("Success getMessageTypesIds " + typesIds.Count);
}
catch (Exception ex)
{
logger.addMessage("Error in getMessageTypesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getMessageTypesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
foreach (var typeId in typesIds)
{
List<Object> type = new List<object>();
Object[] getTypeParams = new object[1];
getTypeParams[0] = typeId;
//string includeName = "";
try
{
type = (List<Object>)getType.Invoke(sqlDB, getTypeParams);
Debug.WriteLine("Success getType");
}
catch (Exception ex)
{
logger.addMessage("Error in getType " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getType " + ex.Message + " Inner: " + ex.InnerException.Message);
}
types.Add(new Common.Model.MType((string)type[0], (string)type[1], (string)type[2], (string)type[3], (string)type[4], (string)type[5], (Guid)type[6]));
Debug.WriteLine("Success adding new type: " + (string)type[0] + " " + (string)type[1] + " " + (string)type[2] + " " + (string)type[3] + " " + (string)type[4] + " " + (string)type[5] + " " + (Guid)type[6]);
}
string sourceSystem = "";
string destSystem = "";
List<Object> message = new List<object>();
Object[] getMessageParams = new Object[1];
getMessageParams[0] = id;
try
{
message = (List<Object>)getMessage.Invoke(sqlDB, getMessageParams);
Debug.WriteLine("Success getMessageParams");
}
catch (Exception ex)
{
logger.addMessage("Error in getMessageTypesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getMessageTypesIds: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
messages.Add(new Common.Model.Message(types, message[0].ToString(), (int)message[1], message[2].ToString(), message[3].ToString(), message[4].ToString(), message[5].ToString(), message[6].ToString(), message[7].ToString(), message[8].ToString(), message[9].ToString()));
Debug.WriteLine("Success adding new Message: " + message[0].ToString() + " " + (int)message[1] + " " + message[2].ToString() + " " + message[3].ToString() + " " + message[4].ToString() + " " + message[5].ToString() + " " + message[6].ToString() + " " + message[7].ToString() + " " + message[8].ToString() + " " + message[9].ToString());
}
#endregion
Object[] getInterfaceFromIdParam = new Object[1];
getInterfaceFromIdParam[0] = @interface;
List<Object> tempInterface = new List<object>();
try
{
tempInterface = (List<Object>)getInterfaceFromId.Invoke(sqlDB, getInterfaceFromIdParam);
Debug.WriteLine("Success getInterfaceFromId " + tempInterface.Count);
}
catch (Exception ex)
{
logger.addMessage("Error in getInterfaceFromId : " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getInterfaceFromId : " + ex.Message + " Inner: " + ex.InnerException.Message);
}
interfaces.Add(new Common.Model.Interface(messages, definitions, includes, Convert.ToString(tempInterface[0]), Convert.ToString(tempInterface[1]), Convert.ToInt32(tempInterface[2]), Convert.ToInt32(tempInterface[3]), Convert.ToBoolean(tempInterface[4])));
Debug.WriteLine("Success adding new interface: " + interfaces.Last().Name);
}
#endregion
#region InputOutputNumber
List<int> inputs = new List<int>();
List<int> outputs = new List<int>();
int inputCount = 0;
int outputCount = 0;
Object[] getSysInputNumParams = new Object[1];
getSysInputNumParams[0] = systemId;
try
{
inputs = (List<int>)getSysInputs.Invoke(sqlDB, getSysInputNumParams);
if (inputs != null)
{
inputCount = inputs.Count;
Debug.WriteLine("Success getSysInputNum inputs = " + inputCount);
}
else
Debug.WriteLine("Success getSysInputNum inputs = 0");
}
catch (Exception ex)
{
logger.addMessage("Error in getSysInputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getSysInputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
Object[] getSysOutputNumParams = new Object[1];
getSysOutputNumParams[0] = systemId;
try
{
outputs = (List<int>)getSysOutputs.Invoke(sqlDB, getSysOutputNumParams);
if (outputs != null)
{
outputCount = outputs.Count;
Debug.WriteLine("Success getSysOutputNum outputs = " + outputCount);
}
else
Debug.WriteLine("Success getSysOutputNum outputs = 0");
}
catch (Exception ex)
{
logger.addMessage("Error in getSysOutputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
Debug.WriteLine("Error in getSysOutputNum: " + ex.Message + " Inner: " + ex.InnerException.Message);
}
#endregion
Common.Model.System system = null;
try
{
system = new Common.Model.System(interfaces, enums, structs, sysName, inputCount, outputCount, inputs, outputs);
Debug.WriteLine("Success adding new system");
}
catch (Exception ex)
{
logger.addMessage("Error in creating new system: " + ex.Message);
Debug.WriteLine("Error in creating new system: " + ex.Message);
}
MainNet.Systems.Add(system);
Debug.WriteLine("Done! you now have a new system with: " + interfaces.Count + " interfaces And " + enums.Count + " Enums and " + structs.Count + " Structs, The name is: " + sysName + " numOfInput: " + inputCount + " numOfOutput: " + outputCount);
#endregion
}
#endregion
回答1:
The dispatcher is being used incorrectly here
The Dispatcher can be used to marshal code onto the UI thread, at a specified priority if desired. The code does not get executed and return immediately, but instead gets run at the priority specified according to the DispatcherPriority order.
Basically your code is saying
- Create a List
- >> Queue code to populate the list on the UI thread at a later time
- If list is not null, execute some code
The list will always be null because the code to populate it hasn't been run yet. Its only been queued to run once when available.
The correct way to do this would be to populate your data on the background worker, and then marshal the results back onto the UI thread to populate your UI.
Note that objects can only be modified on the thread at which they were created on. So if you have some objects you plan on using and/or modifying from the UI later on, you should see something like this:
- Create objects
- Start BackgroundWorker to get data
- BackgroundWorker obtains data on background thread without locking up UI
- BackgroundWorker finishes and uses Dispatcher to run code on the UI thread that will update objects created at the first step with results
来源:https://stackoverflow.com/questions/23504176/wpf-mvvm-backgroundworker-busyindicator