Невозможный (как я очень не хочу использовать это слово), ошибка свинчивания резьбы?

Я не уверен, что понимаю, почему вы хотите условное выражение, поскольку ваши then и else совпадают.

В любом случае, я думаю, что вы ищете что-то вроде этого:

Percentage =
DIVIDE (
    COUNT ( Foods[Fruit] ),
    CALCULATE ( COUNT ( Foods[Fruit] ), ALLEXCEPT ( Foods, Foods[Group] ) )
)

Функция ALLEXCEPT удаляет весь контекст фильтра, кроме столбца Group, так что вы получаете все [115 ] в этом Group.

Result

6
задан Community 8 February 2017 в 14:10
поделиться

5 ответов

Я подозреваю, что InvokedRevoked мог бы лгать Вам. Управление WinForm задерживает создание базового Win32 HWND Управления, пока для вызова метода на самом деле не нужен он. InvokeRequired возвратит false, если HWND еще не был создан.

Для подробного объяснения см.: "Таинственный Зависают или Большой Обман InvokeRequired"

Если Ваш фоновый поток запросит InvokeRequired, прежде чем поток UI заставил Управление лениво создавать свой HWND, InvokeRequired (неправильно) скажет Вашему фоновому потоку, что это не должно использовать, Вызывают () для пасования назад управления к потоку UI. Когда фоновый поток затем получает доступ к Управлению, BAM! "InvalidOperationException: операция перекрестного потока, не допустимая!"

Поток UI может вручную вынудить Управление создать свой дескриптор HWND, чтобы так Управлять. InvokeRequired будет знать, что поток UI является владельцем Управления:

Control control = new Control();
IntPtr handle = control.Handle; // if you ask for HWND, it will be created
9
ответ дан 8 December 2019 в 18:42
поделиться

Большинство людей видит, что ошибка и видит одну вещь, "Вы не получаете доступ к этому управлению от основного потока UI". В действительности у Вас может быть 100 потоков UI, если Вы хотите (поведение для этого не определяется, но поддерживается). Возможности являются panelMain, создается на другом потоке к (этому); я не вижу код - но похоже на создание его в рабочем/потоке.

Для подтверждения поведения пробуют это:

Action addAction = new Action (
   new delegate { panelMain.Controls.Add(UCLoadingScreen); } )
if(panelMain.InvokeRequired)
{
   panelMain.Invoke(addAction); // Breakpoint here.
}
else
{
   addAction();
}

Будьте подготовлены к другой ошибке (дочерний элемент управления на другом потоке к, он - родитель, не уверенный, какую ошибку Вы получите, но я вполне уверен, Вы будете). Это не фиксация.

Фабрика зафиксирует это однако:

public void CreateControl<T>() where T : new()
{
    if(InvokeRequired)
    {
        return (T)Invoke(new Func<T>(CreateControl<T>()));
    }
    return new T();
}

Править: panelMain не мог бы быть потоком 'нарушитель', как я сказал, порождение средств управления от различных потоков является результатами в очень неопределенном поведении. Удостоверьтесь, что все Ваши средства управления создаются в контексте потока Вашей основной формы.

5
ответ дан 8 December 2019 в 18:42
поделиться

Нет такой вещи как невозможная ошибка свинчивания резьбы!

0
ответ дан 8 December 2019 в 18:42
поделиться

Я надеюсь, что это работает для вас. Я предполагаю, что ваши графические материалы находятся на одной нити. Просто инициализируйте этот синглтон и полагайтесь на него всякий раз, когда вам захочется вызвать свойство Control.InvokeRequired.

Cheers,

-Greg

public sealed class UiThread
{
  #region Singleton
  // Singleton pattern implementation taken from Jon Skeet's C# and .NET article www.yoda.arachsys.com/csharp/singleton.html

  UiThread() { }

  public static UiThread Instance { get { return Nested.instance; } }

  class Nested
  {
     // Explicit static constructor to tell C# compiler
     // not to mark type as beforefieldinit
     static Nested() { }

     internal static readonly UiThread instance = new UiThread();
  }
  #endregion

  int _uiThreadId = 0;

  public void SetUiThread(Thread thread)
  {
     if (_uiThreadId != 0)
        throw new ApplicationException("UI Thread has already been established!");

     if (thread.ManagedThreadId == 0)
        throw new ArgumentException("Unexpected thread id value of 0!");

     if (thread.IsBackground)
        throw new ArgumentException("Supplied thread should not be a background thread!");

     if (thread.IsThreadPoolThread)
        throw new ArgumentException("Supplied thread should not be a thread pool thread!");

     _uiThreadId = thread.ManagedThreadId;
  }

  /// <summary>
  /// It's possible for InvokeRequired to return false when running in background thread.
  /// This happens when unmanaged control handle has not yet been created.
  /// We second-guess Microsoft's implementation in this case, checking against foreground thread's Id.
  /// </summary>
  /// <param name="control">Control to check against.</param>
  public bool InvokeRequired(Control control)
  {
     if (control.InvokeRequired)
        return true;

     IntPtr unmanagedHandle = control.Handle;
     bool newResult = control.InvokeRequired;

     if (unmanagedHandle == IntPtr.Zero)
     {
        // Trace.WriteLine() call here forces unmanagedHandle's initialization, 
        //  even with optimizing compiler.
        Trace.WriteLine(string.Format("Control handle could not be established! Control was {0}.", control.ToString()));
     }

     bool retVal = InvokeRequired();

     // Break whenever the result of our check does not match theirs.
     Debug.Assert(retVal == newResult);

     // Return our InvokeRequired result over theirs 
     //   to keep with the tradition of updating controls from foreground only.
     return retVal;
  }

  /// <summary>
  /// Prefer to use overload with Control argument if at all possible.
  /// It's possible for InvokeRequired to return false when running in background thread.
  /// This happens when unmanaged control handle has not yet been created.
  /// We second-guess Microsoft's implementation in this case, checking against foreground thread's Id.
  /// </summary>
  public bool InvokeRequired()
  {
     if (_uiThreadId == 0)
        throw new ApplicationException("UI Thread has not been established!");

     return (Thread.CurrentThread.ManagedThreadId != _uiThreadId);
  }

}

0
ответ дан 8 December 2019 в 18:42
поделиться

Использовать

if (InvokeRequired)
{
  //invoke
}
else
{
  //do
}
-1
ответ дан 8 December 2019 в 18:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: