When running a program for an extended period, adding a progress bar is an effective way to prevent crashes. If your feature is currently executing, using the Dispatcher class offers a simple and efficient solution. This approach is implemented using WPF windows.
public partial class ProgressBarView : Window
{
ExternalCommandData m_commandData = null;
StrightRigidFrameBridgeModel m_model = null;
Element m_element = null;
ProgressModel m_ProgressModel;
bool applicationCancel = false;
public ProgressBarView(ExternalCommandData commandData, StrightRigidFrameBridgeModel model, Element elem)
{
InitializeComponent();
m_commandData = commandData;
m_model = model;
m_element = elem;
ProgressModel pModel = new ProgressModel();
m_ProgressModel = pModel;
this.DataContext = pModel;
applicationCancel = false;
}
public void StrightRigidFrameBridgeCreater(ExternalCommandData commandData, StrightRigidFrameBridgeModel model, Element elem)
{
using (TransactionGroup transGroup = new TransactionGroup(commandData.Application.ActiveUIDocument.Document, "Create Rebar"))
{
transGroup.Start("Create Stright Rigid Frame Bridge");
ICollection elementIds = new List () { elem.Id };
for (int i = 0; i < (model.ListBoxGriderModel.Count - 1); i++)
{
m_ProgressModel.ProgressInfomation = "Remaining " + (model.ListBoxGriderModel.Count - 1 - i - 1).ToString() + " Segments";
m_ProgressModel.ProgressValue = double.Parse(i.ToString()) / (model.ListBoxGriderModel.Count - 2) * 100;
System.Windows.Forms.Application.DoEvents();
BoxGriderModel boxGriderModelI = model.ListBoxGriderModel[i];
BoxGriderModel boxGriderModelJ = model.ListBoxGriderModel[i + 1];
#region Assign family parameters to corresponding family parameters
#endregion
Transaction transaction1 = new Transaction(commandData.Application.ActiveUIDocument.Document);
transaction1.Start("Change Family Parameters");
elem.LookupParameter("iH").Set(MillimetersToUnits(boxGriderModelI.XLG)); // Height of section i of variable cross-section box girder
elem.LookupParameter("iHI5").Set(MillimetersToUnits(boxGriderModelI.DBH)); // Height of i-section bottom plate
elem.LookupParameter("iT").Set(MillimetersToUnits(boxGriderModelI.FBH)); // Width of i-section web plate
elem.LookupParameter("iHI1").Set(MillimetersToUnits(boxGriderModelI.TBH)); // Height of top plate of i-section
elem.LookupParameter("jH").Set(MillimetersToUnits(boxGriderModelJ.XLG)); // Height of section j of variable cross-section box girder
elem.LookupParameter("jHI5").Set(MillimetersToUnits(boxGriderModelJ.DBH)); // Height of j-section bottom plate
elem.LookupParameter("jT").Set(MillimetersToUnits(boxGriderModelJ.FBH)); // Width of j-section web plate
elem.LookupParameter("jHI1").Set(MillimetersToUnits(boxGriderModelJ.TBH)); // Height of top plate of j-section
elem.LookupParameter("BeamLength").Set(MillimetersToUnits(boxGriderModelJ.JDCD)); // Segment length of variable section box girder
elem.LookupParameter("detZ").Set(MillimetersToUnits(boxGriderModelI.SJGC) - MillimetersToUnits(boxGriderModelJ.SJGC)); // Height difference between two z-sections
elem.LookupParameter("detY").Set(MillimetersToUnits(boxGriderModelI.Y_Coordinate) - MillimetersToUnits(boxGriderModelJ.Y_Coordinate)); // Height difference between two y-sections
transaction1.Commit();
#region Place the family with changed parameters in the corresponding position
Transaction transaction2 = new Transaction(commandData.Application.ActiveUIDocument.Document);
transaction2.Start("Copy the family to the corresponding location");
XYZ point = new XYZ(MillimetersToUnits(boxGriderModelI.X_Coordinate), MillimetersToUnits(boxGriderModelI.Y_Coordinate), MillimetersToUnits(boxGriderModelI.SJGC));
LocationPoint familyInstancePoint = elem.Location as LocationPoint;
XYZ translationVector = point.Subtract(familyInstancePoint.Point);
ElementTransformUtils.CopyElements(commandData.Application.ActiveUIDocument.Document, elementIds, translationVector);
transaction2.Commit();
#endregion
if (applicationCancel == true)
{
break;
}
}
if (applicationCancel == true)
{
transGroup.RollBack();
this.Close();
}
else
{
transGroup.Assimilate();
}
}
}
private double MillimetersToUnits(double value)
{
return UnitUtils.ConvertToInternalUnits(value, DisplayUnitType.DUT_MILLIMETERS);
}
private void window_Loaded(object sender, RoutedEventArgs e)
{
Thread thread = new Thread(execute);
thread.Start();
}
private void execute()
{
this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (ThreadStart)delegate ()
{
StrightRigidFrameBridgeCreater(m_commandData, m_model, m_element);
});
}
private void cancelAsyncButton_Click(object sender, RoutedEventArgs e)
{
this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (ThreadStart)delegate ()
{
applicationCancel = true;
});
}
}
The code above uses System.Windows.Forms.Application.DoEvents() to continuously switch control between threads and the main program while updating the progress bar based on the current progress.
When using the Dispatcher class, ensure you handle exceptions properly with try-catch blocks and close threads promptly.
Note: The approach shown in this code may cause some unintended behavior. You might notice components being generated one by one, which can feel awkward. To improve this, consider optimizing the code by wrapping the entire generation process within a single transaction. This is particularly important when idle programs are running, as DoEvents can allow those processes to execute, potentially causing errors. Since the original code is missing, a detailed revision is omitted here, but this guideline should help you avoid common pitfalls.













Must log in before commenting!
Sign Up