Left for a couples hours with entity screen w/ticket widgets open and came back to crash with OutOfMemoryException

Unfortunately it is not my db to share.

But it’s complete hung now on the entity screen. Not OutOfMemory but getting there. It’s lasted a lot longer once I got rid of a bunch of ternary expressions.

REMOVED IMAGE BECAUSE OF CUSTOMER NAME

2020-11-22_11;53_1606067593_taskmgr

Call stack:

System.dll!System.Text.RegularExpressions.Regex.Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout, bool useCache) Line 269
	at f:\dd\NDP\fx\src\regex\system\text\regularexpressions\Regex.cs(269)
System.dll!System.Text.RegularExpressions.Regex.IsMatch(string input, string pattern) Line 726
	at f:\dd\NDP\fx\src\regex\system\text\regularexpressions\Regex.cs(726)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.FunctionRegistry.ExecuteFunctions.AnonymousMethod__2(Samba.Services.Implementations.PrinterModule.ValueChangers.IFunctionData<object> x) Line 562
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\FunctionRegistry.cs(562)
System.Core.dll!System.Linq.Enumerable.WhereSelectEnumerableIterator<Samba.Services.Implementations.PrinterModule.ValueChangers.IFunctionData<object>, Samba.Services.Implementations.PrinterModule.ValueChangers.FunctionExecutor>.MoveNext()
System.Core.dll!System.Linq.Enumerable.ConcatIterator<Samba.Services.Implementations.PrinterModule.ValueChangers.FunctionExecutor>(System.Collections.Generic.IEnumerable<Samba.Services.Implementations.PrinterModule.ValueChangers.FunctionExecutor> first, System.Collections.Generic.IEnumerable<Samba.Services.Implementations.PrinterModule.ValueChangers.FunctionExecutor> second)
System.Core.dll!System.Linq.Buffer<Samba.Services.Implementations.PrinterModule.ValueChangers.FunctionExecutor>.Buffer(System.Collections.Generic.IEnumerable<Samba.Services.Implementations.PrinterModule.ValueChangers.FunctionExecutor> source)
System.Core.dll!System.Linq.OrderedEnumerable<Samba.Services.Implementations.PrinterModule.ValueChangers.FunctionExecutor>.GetEnumerator()
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.FunctionRegistry.ExecuteFunctions<Samba.Domain.Models.Tickets.OrderTagValue>(string content, System.Lazy<Samba.Domain.Models.Tickets.OrderTagValue> model) Line 566
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\FunctionRegistry.cs(566)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.OrderTagValue>.ReplaceValues(string templatePart, Samba.Domain.Models.Tickets.OrderTagValue model, Samba.Domain.Models.Settings.PrinterTemplate printerTemplate) Line 195
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(195)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.OrderTagValue>.GetValue(Samba.Domain.Models.Settings.PrinterTemplate template, Samba.Domain.Models.Tickets.OrderTagValue model) Line 184
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(184)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<System.__Canon>.GetValue.AnonymousMethod__0(System.__Canon x) Line 108
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(108)
System.Core.dll!System.Linq.Enumerable.SelectManyIterator<Samba.Domain.Models.Tickets.OrderTagValue, string>(System.Collections.Generic.IEnumerable<Samba.Domain.Models.Tickets.OrderTagValue> source, System.Func<Samba.Domain.Models.Tickets.OrderTagValue, System.Collections.Generic.IEnumerable<string>> selector)
mscorlib.dll!string.Join(string separator, System.Collections.Generic.IEnumerable<string> values) Line 180
	at f:\dd\ndp\clr\src\BCL\system\string.cs(180)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.OrderTagValue>.GetValue(Samba.Domain.Models.Settings.PrinterTemplate template, System.Collections.Generic.IEnumerable<Samba.Domain.Models.Tickets.OrderTagValue> models) Line 108
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(108)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.OrderTagValue>.Replace.AnonymousMethod__0() Line 79
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(79)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.Helper.FormatData<System.__Canon>(string data, string tag, System.Func<System.__Canon> valueFunc, System.Func<System.__Canon, string> toStringFunc) Line 13
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\Helper.cs(13)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.OrderTagValue>.Replace(Samba.Domain.Models.Settings.PrinterTemplate template, string content, System.Collections.Generic.IEnumerable<Samba.Domain.Models.Tickets.OrderTagValue> models) Line 79
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(79)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.OrderValueChanger.ReplaceTemplateValues(string templatePart, Samba.Domain.Models.Tickets.Order model, Samba.Domain.Models.Settings.PrinterTemplate template) Line 104
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\OrderValueChanger.cs(104)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.Order>.ReplaceValues(string templatePart, Samba.Domain.Models.Tickets.Order model, Samba.Domain.Models.Settings.PrinterTemplate printerTemplate) Line 194
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(194)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.Order>.GetValue(Samba.Domain.Models.Settings.PrinterTemplate template, Samba.Domain.Models.Tickets.Order model) Line 184
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(184)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<System.__Canon>.GetValue.AnonymousMethod__0(System.__Canon x) Line 108
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(108)
System.Core.dll!System.Linq.Enumerable.SelectManyIterator<Samba.Domain.Models.Tickets.Order, string>(System.Collections.Generic.IEnumerable<Samba.Domain.Models.Tickets.Order> source, System.Func<Samba.Domain.Models.Tickets.Order, System.Collections.Generic.IEnumerable<string>> selector)
mscorlib.dll!string.Join(string separator, System.Collections.Generic.IEnumerable<string> values) Line 172
	at f:\dd\ndp\clr\src\BCL\system\string.cs(172)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.Order>.GetValue(Samba.Domain.Models.Settings.PrinterTemplate template, System.Collections.Generic.IEnumerable<Samba.Domain.Models.Tickets.Order> models) Line 108
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(108)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.Order>.Replace.AnonymousMethod__0() Line 79
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(79)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.Helper.FormatData<System.__Canon>(string data, string tag, System.Func<System.__Canon> valueFunc, System.Func<System.__Canon, string> toStringFunc) Line 13
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\Helper.cs(13)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.Order>.Replace(Samba.Domain.Models.Settings.PrinterTemplate template, string content, System.Collections.Generic.IEnumerable<Samba.Domain.Models.Tickets.Order> models) Line 79
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(79)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.TicketValueChanger.ReplaceTemplateValues(string templatePart, Samba.Domain.Models.Tickets.Ticket model, Samba.Domain.Models.Settings.PrinterTemplate template) Line 47
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\TicketValueChanger.cs(47)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.Ticket>.ReplaceValues(string templatePart, Samba.Domain.Models.Tickets.Ticket model, Samba.Domain.Models.Settings.PrinterTemplate printerTemplate) Line 194
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(194)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.ValueChangers.AbstractValueChanger<Samba.Domain.Models.Tickets.Ticket>.GetValue(Samba.Domain.Models.Settings.PrinterTemplate template, Samba.Domain.Models.Tickets.Ticket model) Line 184
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\ValueChangers\AbstractValueChanger.cs(184)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.TicketFormatter.GetFormattedTicket(Samba.Domain.Models.Tickets.Ticket ticket, System.Collections.Generic.List<Samba.Domain.Models.Tickets.Order> lines, Samba.Domain.Models.Settings.PrinterTemplate printerTemplate, int lineCount) Line 41
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\TicketFormatter.cs(41)
Samba.Services.dll!Samba.Services.Implementations.PrinterModule.PrinterService.GetPrintingContent(Samba.Domain.Models.Tickets.Ticket ticket, string format, int width, int mergeLinesMethod) Line 140
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Services\Implementations\PrinterModule\PrinterService.cs(140)
Samba.Presentation.ClientLibrary.dll!Samba.Presentation.ClientLibrary.Modules.TicketModule.Widgets.TicketLister.TicketViewData.TicketData.get() Line 34
	at C:\Users\Vehbi\Documents\Source\Repos\sambapos-v5-pro\Samba.Presentation.ClientLibrary\Modules\TicketModule\Widgets\TicketLister\TicketViewData.cs(34)
[Native to Managed Transition]
[Managed to Native Transition]
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.GetValue(object item, int level)
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.RawValue(int k)
PresentationFramework.dll!MS.Internal.Data.PropertyPathWorker.RawValue()
PresentationFramework.dll!MS.Internal.Data.ClrBindingWorker.RawValue()
PresentationFramework.dll!System.Windows.Data.BindingExpression.TransferValue(object newValue, bool isASubPropertyChange)
PresentationFramework.dll!System.Windows.Data.BindingExpression.Activate(object item)
PresentationFramework.dll!System.Windows.Data.BindingExpression.AttachToContext(System.Windows.Data.BindingExpression.AttachAttempt attempt)
PresentationFramework.dll!System.Windows.Data.BindingExpression.AttachOverride(System.Windows.DependencyObject target, System.Windows.DependencyProperty dp)
PresentationFramework.dll!System.Windows.Data.BindingExpressionBase.OnAttach(System.Windows.DependencyObject d, System.Windows.DependencyProperty dp)
PresentationFramework.dll!System.Windows.StyleHelper.GetInstanceValue(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, System.Windows.DependencyObject container, System.Windows.FrameworkElement feChild, System.Windows.FrameworkContentElement fceChild, int childIndex, System.Windows.DependencyProperty dp, int i, ref System.Windows.EffectiveValueEntry entry)
PresentationFramework.dll!System.Windows.StyleHelper.GetChildValueHelper(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, ref MS.Utility.ItemStructList<System.Windows.ChildValueLookup> valueLookupList, System.Windows.DependencyProperty dp, System.Windows.DependencyObject container, MS.Internal.FrameworkObject child, int childIndex, bool styleLookup, ref System.Windows.EffectiveValueEntry entry, out System.Windows.ValueLookupType sourceType, System.Windows.FrameworkElementFactory templateRoot)
PresentationFramework.dll!System.Windows.StyleHelper.GetChildValue(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, System.Windows.DependencyObject container, int childIndex, MS.Internal.FrameworkObject child, System.Windows.DependencyProperty dp, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord> childRecordFromChildIndex, ref System.Windows.EffectiveValueEntry entry, out System.Windows.ValueLookupType sourceType, System.Windows.FrameworkElementFactory templateRoot)
PresentationFramework.dll!System.Windows.StyleHelper.GetValueFromTemplatedParent(System.Windows.DependencyObject container, int childIndex, MS.Internal.FrameworkObject child, System.Windows.DependencyProperty dp, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord> childRecordFromChildIndex, System.Windows.FrameworkElementFactory templateRoot, ref System.Windows.EffectiveValueEntry entry)
PresentationFramework.dll!System.Windows.StyleHelper.ApplyTemplatedParentValue(System.Windows.DependencyObject container, MS.Internal.FrameworkObject child, int childIndex, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord> childRecordFromChildIndex, System.Windows.DependencyProperty dp, System.Windows.FrameworkElementFactory templateRoot)
PresentationFramework.dll!System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(System.Windows.DependencyObject container, MS.Internal.FrameworkObject child, int childIndex, ref MS.Utility.FrugalStructList<System.Windows.ChildRecord> childRecordFromChildIndex, bool isDetach, System.Windows.FrameworkElementFactory templateRoot)
PresentationFramework.dll!System.Windows.FrameworkTemplate.InvalidatePropertiesOnTemplate(System.Windows.DependencyObject container, object currentObject)
PresentationFramework.dll!System.Windows.FrameworkTemplate.HandleBeforeProperties(object createdObject, ref System.Windows.DependencyObject rootObject, System.Windows.DependencyObject container, System.Windows.FrameworkElement feContainer, System.Windows.Markup.INameScope nameScope)
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent.AnonymousMethod__2(object sender, System.Xaml.XamlObjectEventArgs args)
System.Xaml.dll!System.Xaml.XamlObjectWriter.OnBeforeProperties(object value)
System.Xaml.dll!System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(MS.Internal.Xaml.Context.ObjectWriterContext ctx)
System.Xaml.dll!System.Xaml.XamlObjectWriter.WriteEndObject()
System.Xaml.dll!System.Xaml.XamlWriter.WriteNode(System.Xaml.XamlReader reader)
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadTemplateXaml(System.Xaml.XamlReader templateReader, System.Xaml.XamlObjectWriter currentWriter)
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadTemplateXaml(System.Xaml.XamlObjectWriter objectWriter)
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(System.Windows.DependencyObject container, System.Windows.Markup.IComponentConnector componentConnector, System.Windows.Markup.IStyleConnector styleConnector, System.Collections.Generic.List<System.Windows.DependencyObject> affectedChildren, System.Windows.UncommonField<System.Collections.Hashtable> templatedNonFeChildrenField)
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadContent(System.Windows.DependencyObject container, System.Collections.Generic.List<System.Windows.DependencyObject> affectedChildren)
PresentationFramework.dll!System.Windows.StyleHelper.ApplyTemplateContent(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, System.Windows.DependencyObject container, System.Windows.FrameworkElementFactory templateRoot, int lastChildIndex, System.Collections.Specialized.HybridDictionary childIndexFromChildID, System.Windows.FrameworkTemplate frameworkTemplate)
PresentationFramework.dll!System.Windows.FrameworkTemplate.ApplyTemplateContent(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> templateDataField, System.Windows.FrameworkElement container)
PresentationFramework.dll!System.Windows.FrameworkElement.ApplyTemplate()
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize)
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize)
PresentationFramework.dll!System.Windows.Controls.WrapPanel.MeasureOverride(System.Windows.Size constraint)
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize)
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize)
PresentationCore.dll!System.Windows.ContextLayoutManager.UpdateLayout()
PresentationCore.dll!System.Windows.ContextLayoutManager.UpdateLayoutCallback(object arg)
PresentationCore.dll!System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
PresentationCore.dll!System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandlerCore(object resizedCompositionTarget)
PresentationCore.dll!System.Windows.Media.MediaContext.AnimatedRenderMessageHandler(object resizedCompositionTarget)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler)
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl()
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object state)
WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(object obj)
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 980
	at f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs(980)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 928
	at f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs(928)
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Line 917
	at f:\dd\ndp\clr\src\BCL\system\threading\executioncontext.cs(917)
WindowsBase.dll!MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext executionContext, System.Threading.ContextCallback callback, object state)
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke()
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue()
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled)
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs)
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler)
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs)
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam)
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame)
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame)
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore)
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window)
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window)
Samba.Presentation.exe!Samba.Presentation.App.Main()

Ealier when the entity screen would refresh and hang for a second and a half this was the call stack:

2020-11-22_11;49_1606067372_devenv

Ticket Template for lister widgets:

[LAYOUT]
<L00><size 26><color Black>[='{TICKET STATE:Pre-Order}'] {TICKET TYPE} #{TICKET NO}</color></size><br/>
[=('{TICKET TAG:Promise Time}' == '' ? '' : '<L00><size 26><color White>Promise Time: {TICKET TAG:Promise Time}</color></size><br/>')]
{CALL:format.SqlMins('{TICKET TAG:PromiseDateTime}')}

<L00><size 26><color White>Open for {CREATION MINUTES} min.</color></size><br/>
<L00><size 26><color White>{ENTITY NAME:Tables} {ENTITY DATA:Customers:Name}</color></size><br/>

{ORDERS}
<L00>
<L00><color Black><bold><size 26>{NOTE}</size></bold></color>
<C00><color Green><size 24><font Calibri>[='         {GROUP KEY}      ']</font></size></color><br/>

[ORDERS]
<L00><color Black><bold><size 26><font Calibri>{QUANTITY} {PRODUCT NAME}</font></size></bold></color><font Consolas> <color DarkRed><size 20><italic>{PORTION}</italic></size></color></font><br/>
{SORTED ORDER TAGS}

[ORDERS:Gift]
<L00><color Green><bold><size 20><font Calibri>{QUANTITY} {PRODUCT NAME}</font></size></bold></color><font Consolas> <color red><size 20><italic>{PORTION}</italic></size></color></font><bold>Gift</bold><br/>
{SORTED ORDER TAGS}

[ORDERS:Void]
<L00><s><color Red><bold><size 16><font Calibri>{QUANTITY} {PRODUCT NAME}</font></size></bold></color><font Consolas> <color #FF55FF33><size 14><italic><if '{PORTION' != ''>{PORTION}</if></italic></size></color></font></s><bold> Void</bold><br/>

[SORTED ORDER TAGS]
<L00><size 22><color Black><font Calibri>    {ORDER TAG QUANTITY} {ORDER TAG NAME} {ORDER TAG NOTE}</font></color></size><br/>

Script being called from the template:

function SqlMins(inputDateTimeString)
{
    if (inputDateTimeString == '')
    {
        return '';
    }
    
    var openString = '<L00><size 26><color White>';
    var closeString = '</color></size><br/>';
    
    var q = "SELECT DATEDIFF(MINUTE, GETDATE(), '" + inputDateTimeString + "') AS Mins, CONVERT(VARCHAR(8), CAST('" + inputDateTimeString + "' AS TIME) , 100) AS Time;";
    var r = sql.Query(q).First;
    var rArray = r.split(',');
    var mins = rArray[0];
    var time = rArray[1];
    return openString + 'DUE IN ' + mins + ' mins AT ' + time + closeString;
}

I’ll leave SambaPOS running for now in case I can provide more info while the debugger is attached.

I have dotMemory and dotTrace installed though I’m still learning how to use them. If one knows what I can grab from them and tells me how I can provide that.

There are 20 tickets open right now btw

Snapshot from Perf Viewer:

2020-11-22_12;26_1606069565_dotTraceView64

What is your auto refresh set to in properties for the widgets?

6 seconds right now
1-5 were a no-go from the start

I don’t think they’ll have that many tickets open at once, but it happened Friday night so I’m trying to narrow down the suspect.

Initially I had ternary expressions running on every order tag for conditional formatting and everything would grind to a halt right quick.

10ms per order tag doesn’t sound like much. Unless it’s a pizza with 10 order tags. 4 pizzas per ticket. 10 tickets open and all of a sudden there’s a 4s process time plus the overhead of the query and display.

You could set it to 0 and let new tickets refresh it.

1 Like

I always thought 0 was just continuous refresh. :man_facepalming:

I’ll give it a shot. Thanks!

No by default new tickets trigger a refresh. 0 allows this only above zero it will force one on top of the new tickets causing one.

Usually this is enough for most people. Expecially if your doing calls etc. It can reduce the resources needed. However we do have some issues with entity screens and it not dumping the memory it will just grow. I’m not smart enough to truly understand it.

1 Like

Widgets don’t seem to be refreshing on new tickets:

After clearing data:

Well that is different… Create a ticket from another terminal and it will. Your using something else to insert tickets… im not sure if it will trigger the event or not. I dont think Graphql triggers it without sending a message. I was referring to physical terminals. But I see now your not relying on that.

Yeah that’s just piping in test orders with GQL.

If I have to manually trigger the entity screen refresh on the entity screens on message received, I can see that causing more overhead than just a set refresh interval.

Is there any way to constrain the amount of tickets pulled at each refresh? Say, only load the top 5 and not all tickets?

OutOfMemoryException happens when SP tries to use more than the maximum available memory. The RAM use is limited in practice to around 1.2 GB or less in SambaPOS becuase it’s a 32 bit .NET app.

The issue comes from memory leaks related to script expression evaluations which are launched asynchronously. The expression service instantiates a new ScriptEngine every time an expression needs to be evaluated. In cases where the expression is evaluated in the background (such as a widget refresh process) the Script Engine and associated memory is never freed by the .NET Garbage Collector because the task is launched using a “fire task and forget” coding pattern within SP. The expression service returns a result but the scheduled task itself is never terminated. The task memory is locked because it is owned by .net ROOT object and therefore won’t be freed until the task is terminated. The end result after a while is 1000’s of idle ScriptEngine objects using up more and more RAM until OutOfMemory Exception.

This ScriptEngine memory leak issue also occurs anytime an Automation Command has a Condition containing a ternary expression or script, the Command runs in the background and calls script, or a ticket lister widget containing CALLs to script with auto refresh (such as OP case here) is another example. I don’t remember the other cases right now but there are numerous ways to embed script withing SP and some of those execute the same problematic Task launch code (without a terminate on task completion).

The solution to this is for SP developers to wrap some small sections of .NET code within a special task handler which explicitly terminates the task after completing it’s work in those cases. This would also boost performance significantly in configurations which use script because the .net Garbage Collector wont be working so hard attempting to free memory and continuously failing. Currently it is common for GC to consume 20 to 50% CPU trying to free memory and hence the sluggish performance in such configurations after running them for a while.

The current workaround is to restart SambaPOS regularly and also minimize the use of asynchronous script in the configuration.

I hope developer resources will be sufficient one day to solve this problem and allow SP to rock in script based configurations!

5 Likes

Do you know if there have been any updates for this?

I use a lot of script to create widget labels on custom entity screens and I have been finding recently that I have been having a lot of memory issues with SambaPOS.

I don’t have any advanced way of checking this, but I just watched Task Manager creep up 5Mb each time I switched between 4 entities in a #Table report. Even when returning to an entity that I had already clicked on I noticed that that the RAM usage continued to increase.

@GreatShakesBar - You might want to hold off on your development of this idea that I mentioned in another thread until this uncontrolled memory leak is fixed.

2 Likes

We had to remove all scripts from widgets to address the memory and refresh issues.

I am trying to replace my script tags with direct {REPORT SQL} tags to skip the need to having the call to a jScript function.

The following tag works perfectly when I have only one tag on the entity screen:

Wetsuit:<bold>{REPORT SQL DETAILS:SELECT jsonValueWetsuit AS [Wetsuit] FROM ENTITIES CROSS APPLY OPENJSON(CustomData) WITH (jsonNameWetsuit varchar(50) '$.Name', jsonValueWetsuit varchar(1024) '$.Value') jsonData WHERE jsonNameWetsuit = 'Wetsuit' and Name = '{SETTING:EQUIP-EntityName}':F.Wetsuit}</bold>

BUT when I have multiple REPORT SQL tags on the same screen to pull all of the fields I get completely random and unpredictable results. Take a look at the recording below and you will see sometimes the Wetsuit and BCD values are displayed correctly, but other times they are not.

To further test this I set very simple tags for the Fins, Mask and Computer labels:

Fins:{REPORT SQL DETAILS:SELECT '3' as [Field1]:F.Field1::{0}}
Mask:{REPORT SQL DETAILS:SELECT '1' as [Field1]:F.Field1::{0}}
Computer:{REPORT SQL DETAILS:SELECT '2' as [Field1]:F.Field1::{0}}

So as you can see, there should be no reason for the values of Fins, Mask or Computer to change, however each time the widgets of refreshed the output from these tags seems to be completely random.

Any ideas? Maybe the easiest thing would be to get this memory leak fixed and go back to using the {CALL:} tag to run some script.

Not sure why that’s doing what it is. Maybe something in the query cache, who knows.

Here’s a stored procedure I use to get entity custom field data - see if this returns what you’re expecting:

/* Get Entity Custom Field Value */

IF OBJECT_ID('dbo.p_GetEntityCustomFieldValue') IS NOT NULL
  DROP PROCEDURE dbo.p_GetEntityCustomFieldValue;
GO

CREATE PROCEDURE dbo.p_GetEntityCustomFieldValue
  @EntityPk NVARCHAR(MAX),
  @CustomFieldName NVARCHAR(MAX)
AS
  BEGIN
    SET NOCOUNT ON;

    DECLARE @CustomData NVARCHAR(MAX);
    DECLARE @FieldData NVARCHAR(MAX);
    DECLARE @ReturnValue NVARCHAR(MAX);

    SELECT @CustomData = CustomData
        FROM dbo.Entities
        WHERE Name = @EntityPk;

    DECLARE cur_entity_fields CURSOR LOCAL FAST_FORWARD FOR
    SELECT Value
        FROM OPENJSON(@CustomData);

    OPEN cur_entity_fields;

    FETCH NEXT FROM cur_entity_fields
    INTO @FieldData;

    WHILE @@FETCH_STATUS = 0
      BEGIN

        DECLARE @FieldName NVARCHAR(MAX);
        DECLARE @FieldValue NVARCHAR(MAX);

        SELECT @FieldName  = FieldName,
               @FieldValue = FieldValue
            FROM
          OPENJSON(@FieldData)
          WITH (FieldName NVARCHAR(MAX) '$.Name',
                FieldValue NVARCHAR(MAX) '$.Value');

        IF @FieldName = @CustomFieldName
          BEGIN

            SET @ReturnValue = @FieldValue;

            BREAK;
          END;

        FETCH NEXT FROM cur_entity_fields
        INTO @FieldData;
      END;
    CLOSE cur_entity_fields;
    DEALLOCATE cur_entity_fields;

    SELECT @ReturnValue AS FieldValue;

  END;
GO

Usage:

dbo.p_GetEntityCustomFieldValue @EntityPk = N'Entity Primary Key',
                                @CustomFieldName = N'Custom Field Name Here'

for reporting:

{REPORT SQL DETAILS:dbo.p_GetEntityCustomFieldValue 'Entity Primary Key','Custom Field Name Here':F.FieldValue}

Yeah, I suspect some sort of caching issue. For this reason I am going to stay away form the {REPORT SQL:} tags, I found that by using the SQL helper inside some `[= ]’ script tags I was able to get a reliable output. For example:

My output: <bold>[=sql.Query("SELECT 'Hello world'").First]</bold>

BUT, your idea of using a StoredProcedure was really helpful for two reasons…

  • It will help keep the code required for each label a lot cleaner
  • It will allow me to do some date formatting within SQL, which was something I was originally doing in jScript

The stored procedure I created was as follows - You will see this either outputs a formatted date, or will pass the value of the field, so I can use the same SP for all fields and it will automatically give me an appropriate output…

CREATE PROCEDURE [dbo].[getCustomDataByEntityName]
@entityName varchar (50),
@fieldName varchar (50)
AS
BEGIN
	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.
	SET NOCOUNT ON;

DECLARE @value AS VarChar(50) = (
	SELECT jsonValue 
	FROM ENTITIES 
		CROSS APPLY OPENJSON(CustomData) 
		WITH ( 
			jsonName varchar(50) '$.Name', 
			jsonValue varchar(1024) '$.Value'
			) jsonData 
	WHERE 
		jsonName = @fieldName
		and Name = @entityName
)

IF ISDATE(@value) = 1
	SELECT FORMAT (CONVERT(date,@value), 'dd MMM yy') AS [Output]
ELSE
	SELECT @value AS [Output]

END
GO

I am using this with the script tags I was using. For example…

Last Dive: <bold>[=sql.Query("EXEC dbo.getCustomDataByEntityName @entityName = '{SETTING:EQUIP-EntityName}', @fieldName = 'LastDive'").First]</bold>

This is working great.

2 Likes

How’s the lag with widget refreshing?

It is fully explained in this post…

But essentially, all the label widgets have a Properties>Name set to “CurrentValue” and then on the report (which is in #Table mode) I have Settings>Refreshing Widgets set to “CurrentValue” and I also have the report setup to update a program setting each time a new item is clicked. So, every time the a new item is selected in the report, all widgets with the “CurrentValue” name get refreshed.