Bazaprogram.ru

Новости из мира ПК
8 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

System invalidoperationexception как исправить

.NET Exception Handling – System.Inval > March 29, 2017 Andrew Powell-Morse in dotNET, dotNET Exception Handling

Moving right along through the magical world of our .NET Exception Handling series, today we’re going to cover the System.InvalidOperationException . The System.InvalidOperationException is a fairly common exception, as it is typically thrown when there’s a failed attempt to invoke a method, caused by something other than invalid arguments passed to that method.

In this article, we’ll examine where System.InvalidOperationException sits within the .NET exception hierarchy, look at why System.InvalidOperationExceptions typically appear, and see how to deal with them should you encounter one yourself. Let’s get this party started!

The Technical Rundown

  • All .NET exceptions are derived classes of the System.Exception base class, or derived from another inherited class therein.
  • System.SystemException is inherited from the System.Exception class.
  • System.InvalidOperationException is inherited from the System.SystemException class.

When Should You Use It?

Unlike many exceptions in .NET, you may have noticed that System.InvalidOperationException resides quite close to the top of the exception hierarchy, as a direct descendent of System.SystemException . This typically indicates a .NET exception that is very common, or is applicable in many scenarios, and System.InvalidOperationException (arguably) falls into both camps.

The challenge with describing the System.InvalidOperationException is that it can occur in a wide variety of scenarios. As mentioned in the introduction, a System.InvalidOperationException is thrown when a method invocation fails for a reason other than invalid arguments. The official documentation gives a few potential examples of what might cause this, including:

  • When an IEnumerator.MoveNext call is made on a collection that has since been modified after the enumerator was generated (more on this one later).
  • Calling ResourceSet.GetString if the resource was already closed prior to this call.
  • Modifying XML via the XContainer.Add method, if doing so would generate invalid XML .
  • Attempting to modify the UI from a secondary thread that is not the main/UI thread.

This is by no means an exhaustive list, so it’s impossible to cover all potential scenarios that a System.InvalidOperationException could occur. Instead, to continue our examination, we’ll just take a look at one particular means by which a System.InvalidOperationException is typically raised: Modifying a collection after the enumeration of that collection has been generated, then continuing to utilize the enumeration.

To illustrate this in action, we’ve got our full code example below:

We won’t get into detail about the Utility namespace, but instead we’ll look at the Airbrake.InvalidOperationException namespace, where our problematic code resides. In this somewhat realistic example, we’ve got an interface called IBook , which specifies a few fields ( Author and Title ) for our Book class:

Now, using our Book class, our InvalidExample method generates a List collection called books , and adds a few of my favorites selections to the list. From there, we confirm that our collection contains the five Books we added, then we generate our Enumerator using the foreach loop block. Inside our loop, we output the current book instance, then create a newBook of Robinson Crusoe . We then call books.Add to add our newBook to the collection, and continue the loop using our previously established enumeration :

The trouble is, our enumeration was established back when we had only five books, but before our second call to foreach , we’ve modified the collection and added a sixth book. Sure enough, this throws a System.InvalidOperationException :

If adding new items to the collection during the enumeration is a necessity, the best way to do it is to generate a static enumeration beforehand; one that doesn’t directly access the modified collection each loop. For example, using for , instead of foreach , allows us to reference pre-determined indexes of the collection items, rather than direct collection items during the loop. Here is our slightly modified code to illustrate a successful fix:

The key is to detach enumeration from the collection that is changing. We’ve initially stated that our enumerator will only loop through a total of the first five items (indexes), regardless of what is added to the collection afterward. This produces an expected result without a System.InvalidOperationException :

To get the most out of your own applications and to fully manage any and all .NET Exceptions, check out the Airbrake .NET Bug Handler, offering real-time alerts and instantaneous insight into what went wrong with your .NET code, along with built-in support for a variety of popular development integrations including: JIRA, GitHub, Bitbucket, and much more.

System invalidoperationexception как исправить

Решение проблемы с ошибкой «System.InvalidOperationException: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления ‘имя_элемента_GUI’ не из того потока, в котором он был создан.» заключается в создании и вызове методов-делегатов. Статья написана на основе перевода статьи Rüdiger Klaehn, оригинал см. в [1].

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

Почему такая проблема возникает: ListBox создается в основном потоке (thread), запускающем GUI окна программы и обрабатывающим сообщения главного окна формы. Другие потоки могут быть созданы для поддержки обмена данными с внешними устройствами (сеть Ethernet, COM-порт, USB и т. п.). Эти другие потоки могут обрабатывать события приема данных асинхронно с выполнением основного потока. Поэтому попытка разными потоками что-то записать в ListBox может привести к конфликту с записью в ListBox данных из основного потока GUI интерфейса программы.

Читать еще:  Как включить автоисправление

Как проблему можно решить: для ListBox создаются подпрограммы (методы), через которые выводятся данные в ListBox. Данные выводятся в ListBox только через эти подпрограммы, больше никак. Эти подпрограммы делаются защищенными (thread-safe) для вызова из любых потоков через delegate, InvokeRequired, Invoke.

Программирование интерфейса пользователя через Windows Forms довольно простое, пока вы не используете несколько потоков. Однако всякий раз, когда Вашему приложению нужно выполнить какую-нибудь фактическую работу, становится необходимым использовать поточную обработку (threading), т. е. создать дополнительный поток (thread) или потоки, чтобы обеспечить работоспособность пользовательского интерфейса (скорость отклика UI). В этом случае программирование Windows Forms может стать довольно сложным.

Вы наверное уже знаете, что Windows Forms главным образом не являются потокозащищенными (not thread safe). Например, Вы не можете безопасно прочитать (get) или установить (set) свойство объекта управления (control) Windows.Forms из любого потока, за исключением того потока, который обрабатывает очередь сообщений формы (message queue). Это чрезвычайно важно, когда Вы делаете модификацию своих элементов управления (controls) Ваших Windows Forms из потока очереди сообщений. Могут быть и другие случаи, когда разные потоки вступают в конфликт при доступе к одному и тому же общему ресурсу – например, обработчик события получения данных от внешнего устройства (USB, сокет Ethernet и проч.) должен выводить данные в ListBox, который был создан в главном окне программы. В этом случае выполнение программы может вызывать исключение «System.InvalidOperationException: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления ‘имя_экземпляра_ListBox’ не из того потока, в котором он был создан.».

Само собой, имеется стандартный механизм для решения этой проблемы. Каждый элемент управления (control) Windows Forms имеет свойство InvokeRequired, которое вернет false, если текущий поток является «родным» для контрола, т. е. является потоком очереди сообщений. Также имеется метод Invoke, который делает возможным поставить выполнение делегата (delegate) с параметрами в очередь сообщений управления.

Поскольку делегат выполняется непосредственно из очереди сообщений, то не возникает проблемы с потоками. Однако такой стиль программирования может быть довольно утомительным. Чтобы сделать что-то столь же простое, как установка свойства текста или запрет/разрешение элемента управления, Вам нужно определить отдельный метод, который соответствует делегату.

[Пример: случайные строки (Random Strings)]

Чтобы проиллюстрировать этот метод, я написал маленькую программу на Windows Forms, которая генерирует случайные строки. Вот кусок кода, который показывает, как сделана синхронизация между рабочим потоком (worker thread) и потоком цикла очереди сообщений (message loop thread).

char PickRandomChar( string digits)
<
Thread.Sleep(100);
return digits[random.Next(digits.Length)];
>
delegate void SetBoolDelegate( bool parameter);
void SetInputEnabled( bool enabled)
<
if (!InvokeRequired)
<
button1.Enabled=enabled;
comboBoxDigits.Enabled=enabled;
numericUpDownDigits.Enabled=enabled;
>
else
Invoke( new SetBoolDelegate(SetInputEnabled), new object [] );
>
delegate void SetStringDelegate( string parameter);
void SetStatus( string status) <
if (!InvokeRequired)
labelStatus.Text=status;
else
Invoke( new SetStringDelegate(SetStatus), new object [] );
>
void SetResult( string result) <
if (!InvokeRequired)
textBoxResult.Text=result;
else
Invoke( new SetStringDelegate(SetResult), new object [] );
>
delegate int GetIntDelegate();
int GetNumberOfDigits()
<
if (!InvokeRequired)
return ( int )numericUpDownDigits.Value;
else
return ( int )Invoke( new GetIntDelegate(GetNumberOfDigits), null );
>
delegate string GetStringDelegate();
string GetDigits()
<
if (!InvokeRequired)
return comboBoxDigits.Text;
else
return ( string )Invoke( new GetStringDelegate(GetDigits), null );
>
void Work()
<
try
<
SetInputEnabled( false );
SetStatus( «Working» );
int n=GetNumberOfDigits();
string digits=GetDigits();
StringBuilder text= new StringBuilder ();
for ( int i=0;i!=n;i++)
<
text.Append(PickRandomChar(digits));
SetResult(text.ToString());
>
SetStatus( «Ready» );
>
catch (ThreadAbortException)
<
SetResult( «» );
SetStatus( «Error» );
>
finally
<
SetInputEnabled( true );
>
>
void Start()
<
Stop();
thread= new Thread( new ThreadStart(Work));
thread.Start();
>
void Stop()
<
if (thread!= null )
<
thread.Abort();
thread= null ;
>
>

Здесь используется Thread.Abort, так как это самое простое решение. Если Вы делаете что-то, что не должно быть прервано ни при каких обстоятельствах, то вместо этого Вы должны использовать флаг сигнализации для потока. Здесь приведен простой, но очень повторяющийся код. Имейте в виду, что Вы всегда должны проверить InvokeRequired, потому что вызов Invoke перед созданием очереди сообщений может привести к ошибке. Скачать исходный код проекта (Visual Studio C# 2010) можно по ссылке [7].

[Генерирование потокозащищенных оберток (thread-safe wrappers)]

В предыдущей статье (см. [2]) я показал, как можно автоматически генерировать обертки для классов, чтобы заставить их «неявно» реализовать интерфейс. Тот же метод генерации кода можно расширить, чтобы создать обертки, автоматически обеспечивающие вызов метода в правильном потоке. Я позже подробно опишу, как это работает. В первую очередь рассмотрим, как используется весь механизм. Сначала Вы предоставляете соответствующие свойства в Вашей форме (чекбоксы, листбоксы, и проч.), не заботясь о проблемах с потоками. Это именно то, что Вы хотели бы сделать, если бы совсем не использовали многопоточность.

Затем определите интерфейс, который содержит все свойства и/или методы, к которым может быть получен доступ из других разных потоков.

interface IFormState
<
int NumberOfDigits < get ; >
string Digits < get ; >
string Status < set ; >
string Result < set ; >
bool InputEnabled < set ; >
>

Теперь в методе worker все, что Вы должны сделать – создать thread-safe wrapper и использовать его. Для Вас опущен весь повторяющийся код.

void Work()
<
IFormState state=Wrapper.Create( typeof (IFormState), this );
try
<
state.InputEnabled= false ;
state.Status= «Working» ;
int n=state.NumberOfDigits;
string digits=state.Digits;
StringBuilder text= new StringBuilder ();

for ( int i=0;i <
text.Append(PickRandomChar(digits));
state.Result=text.ToString();
>
state.Status= «Ready» ;
>
catch (ThreadAbortException)
<
state.Status= «Error» ;
state.Result= «» ;
>
finally
<
state.InputEnabled= true ;
>
>

[Как это работает]

Генератор обертки (wrapper generator) использует System.Reflection.Emit для генерации proxy-класса, который содержит все требуемые для интерфейса методы. Это также включает методы доступа к свойствам, у которых есть специальная сигнатура.

Тело этих методов будет делать вызов оригинальных методов напрямую, если InvokeRequired вернул false. Это важно, чтобы удостовериться, что запрос методов также работает, если форма еще не подключена к потоку обработки сообщений.

Если InvokeRequired вернул true, создается делегат, указывающий на оригинальный метод, и созданный делегат передается в метод Invoke формы. Типы делегата кэшируются так, чтобы Вы не получили несколько типов делегата для той же самой сигнатуры метода.

Поскольку wrapper generator использует интерфейс для вызова синхронизации ISynchronizeInvoke, Вы можете применить это решение и для приложений, не использующих Windows-Forms. Все, что нужно сделать – самостоятельно реализовать интерфейс и возможно обработку очереди сообщений.

[Ограничения и возможные проблемы]

Важно понимать, что пока thread-safe wrapper скрывает издержки потоковой синхронизации, из него нельзя делать выход. К примеру, доступ к свойству через thread safe wrapper будет намного медленнее, чем прямой доступ к свойству, если InvokeRequired вернул true. Поэтому если Вам нужно делать многочисленные сложные изменения в Вашей форме из разных потоков, лучшим решением будет создать один отдельный метод для всех действий и вызывать его, вместо того чтобы использовать отдельные вызовы доступа к свойствам.

Также нужно иметь в виду, что не каждый объект может быть безопасно передан из одного потока в другой без синхронизации. В общем случае можно безопасно передавать только типы наподобие int, DateTime и т. п. и иммунные ссылочные типы наподобие string. Будьте особенно осторожны при передаче мутированных ссылочных типов (mutable reference types) наподобие StringBuilder из одного потока к другому. Это будет удачным только в том случае, если будет реально обеспечено, что объект не был модифицирован, пока имеется ссылка на этот объект в других потоках, или все будет удачно если объект является thread safe. Если есть сомнения, то просто передайте глубокую копию вместо ссылки.

Whidbey уменьшает проблемы многопоточности, так как он имеет дополнительную поддержку (см. [5]) для фоновой обработки в Windows Forms, и это тем более делает работу с делегатами намного проще благодаря поддержке анонимных методов (см. [4]), которые являются реально закрытыми (closure, см. [6]).

Установка свойства в Whidbey намного проще:

Точно так же просто получить значение свойства:

К сожалению, Whidbey наверное выйдет в релиз одновременно с Duke Nukem Forever, где-нибудь в 2025 году.

System.InvalidOperationException

Igor Baptista

Terrarian

Attachments

Igor Baptista

Terrarian

Marcus101RR

Master of Ravens

Try the troubleshooting section if you would.

Welcome to PC Support Section.

In order to further assist you, please verify the following information below before proceeding. Please, we remind you that Terraria has certain requirements in order to function properly on your system. If you fail to check these requirements you may encounter errors or issues.

To avoid errors or mistakes, please consider posting your System Specifications. You can obtain this information by Right-Clicking My Computer on your system. You will get basic information about your Processor and RAM. If you wish to get a full detailed list, you can use third party software to determine your specifications or salvage the information from the Device Manager (Advanced Users). You may also use the available and recommended Third Party Software to gain your full system specifications for our technicians.

How to improve your support thread

    Post screenshots of errors

      You can use the

    key on your keyboard to paste your current monitor to the clipboard.

    • Click the window that you want to copy.
    • Press ALT+PRINT SCREEN. Important The text you see on your keyboard might be PrtSc, PrtScn, or PrntScrn. The other text on the Print Screen key is usually SysRq.
    • Paste (CTRL+V) the image into a Microsoft Office program or other application.
  • Provide your system specifications
  • Provide your current mandatory dependencies versions (XNA & .NET)
  • Be reminded this post is intended to simplify your next reply and ease our troubleshooting. If you fail to provide detailed information, it becomes a tedious task to determine what caused your problem. Please be kind enough to follow these simple steps and helpful tips!

    NOTE: If you are using an illegal copy of the game, you will receive no support, this process determines if you are using a legal copy.

    Before you ask, check in these threads to solve your issues:

    Obtaining Logs via Terraria (New)
    There is now a new way to obtain logs of Terraria and try to identify the issue at hand. This little method requires a bit more work, however, we provide you with some instructions on step by step on how to get this working. Please make sure that you check which version of Terraria you have before doing this. Note that the Steam version is slightly easier than the other one.
    Log Location: C:Users DocumentsMy GamesTerrariaLogs

    Steam Version
    There is no special requirement with steam as it is one simple platform.

    1. Open Steam Library .
    2. Right-Click Terraria on the Library and select Properties .
    3. Select General Tab , if not already selected.
    4. Click Set Launch Options .
    5. In the text box insert -logerrors -logfile

    GOG Version
    There are different procedures for the operating system you are using, we will try to get them for all.

    1. Create a shortcut of Terraria Executable .
    2. Right-Click the Shortcut and select Properties .
    3. In Target Box, add at the end the parameters -logerrors -logfile

    Troubleshooting Your Problem with TerrariaServer.exe
    In order to figure out what your problem is with the game, we require that you run the Terraria Server Client (TerrariaServer.exe). This will display any errors or successes on launch. Should there be any errors from the program itself, use the command prompt and copy the error to display it here.

    1. Right click within the Command Prompt.
    2. In the drop-down menu, select Mark.
    3. Once you made a selection, Right Click or Press Enter to copy.
    4. Paste your results in your thread.

    If you have trouble with the above instructions, your system might be showing «Not Responding» or your System may need to be rebooted to start clean.

    Deleting the JSON files to clear Terraria Settings
    Before proceeding any further, please delete the config.json file located in your Terraria Folder under My Documents/My Games. Then start Terraria again, this may fix some unexplained issues, but we wish to make sure you are running a nice and clean installation:

    1. Locate My Documents Folder.
    2. Open My Games Folder.
    3. Open Terraria Folder.
    4. Delete Config.json file from this location.
      • You can also delete the Favorites/Profile files as well, just in case.

    Frequently Asked Questions

    Q: My world has corrupted somehow and will not load properly, what can I do?
    A: You may have corrupted the world by using modded clients, computer shutdown before the world could complete the save, or system failure within Terraria that caused the problem. You can try attempting to load your world using TEdit (Download).

    Q: My game is not launching, or I get errors regarding XNA/.NET Framework!
    A: You can attempt to make sure you have all Game Dependencies first, then try attempting this solution:

    If you don’t feel like sifting through all that, it’s basically to do with the framework permissions.

    This is how you change the right to use Framework/XNA:

    1. Right-Click the specific directory (Listed Below).
    2. Select Properties.
    3. Select the Security Tab
    4. Click on Advanced Option
    5. Select the Owner Tab
    6. Click on the bottom button to Edit.
    7. On this window select the Administrator in the row and make sure to select the Checkboxes below.
    8. Hit Apply and close all the windows.
    9. Try running the game again.

    Do the above for all of the following FOLDERS:

    C:WindowsMicrosoft.NETassemblyGAC_32:
    Microsoft.Xna.Frameworkv4.0_4.0.0.0__842cf8be1de50553
    Microsoft.Xna.Framework.Gamev4.0_4.0.0.0__842cf8be1de50553
    Microsoft.Xna.Framework.Graphicsv4.0_4.0.0.0__842cf8be1de50553
    Microsoft.Xna.Framework.Xactv4.0_4.0.0.0__842cf8be1de50553

    C:WindowsMicrosoft.NETassemblyGAC_MSIL:
    Microsoft.Xna.Framework.Avatarv4.0_4.0.0.0__842cf8be1de50553
    Microsoft.Xna.Framework.GamerServicesv4.0_4.0.0.0__842cf8be1de50553
    Microsoft.Xna.Framework.Input.Touchv4.0_4.0.0.0__842cf8be1de50553
    Microsoft.Xna.Framework.Netv4.0_4.0.0.0__842cf8be1de50553
    Microsoft.Xna.Framework.Storagev4.0_4.0.0.0__842cf8be1de50553
    Microsoft.Xna.Framework.Videov4.0_4.0.0.0__842cf8be1de50553

    Q: Steam has reported that one (1) file has failed verification and was downloaded?
    A: This file is known as the serverconfig.txt file. Originally this file shouldn’t be packed with the game as Terraria should create this file automatically on launch if it is missing or out of date. Due to it being changed and updated by server owners, the file will constantly fail the verification process. This has no effect on playing the game, and can be ignored.

    Q: I am experiencing low frame rate for Terraria, but the machine passes as recommended?
    A: If you are using nVidia Control Panel, you can select Terraria.exe process and change the specifications on how your graphic card handles the game. Follow these instructions:

    1. Open nV >On .
    2. Run Terraria and turn Frame Skip to Off .
    3. The application should be running better than your current setup.

    Alternate Solution (The Aero Mode Bug)

    1. Goto your Desktop.
    2. Right Click and Select Personalize.
    3. Enable Aero Mode by selecting an Aero Background Option.
    4. You can also go Fullscreen Mode while Disabled Aero Mode .

    Q: Experiencing an XAudio Driver Issue?
    A: Check this out about the error: http://forums.terraria.org/index.ph. out-due-to-xaudio2_6-dll-on-windows-10.32894/

    Q: Missing XInput Driver for the game?
    A: You can download Microsoft DirectX Web Installer and fix this issue properly. We do not recommend searching for the driver (DLL) manually. Download it here.

    Q: Where can I find my world and player files?
    A: You can find your world and character files based on your system here:

    • Windows: DocumentsMy GamesTerrariaPlayers
    • Mac:

    /Library/Application Support/Terraria/Players
    Linux:

    /.local/share/Terraria/Players

    However, if you’re using Steam Cloud Sync, the files will be in a different location.

    • /userdata/ /105600/remote/players

    Q: Users with Windows 10 and Terraria Crashing (The Encryption Fix)
    A: Apparently Terraria uses a specific encryption method, some OS types do not allow this like Windows 10. This can be fixed!

    Terraria uses the RijndaelManaged class for player encryption, which isn’t FIPS (Federal Information Processing Standard) compliant. There’s a flag in the registry that tells Windows whether it should allow non-compliant encryption methods to be used. The registry key is:

    If the value fipsalgorithmpolicy is present and set to 1, non-compliant algorithms will be blocked and will throw exceptions if you try to use them (like you got). Setting it to 0 should fix the error.

    You might also want to check: HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsaFipsAlgorithmPolicy

    In case you don’t understand the above text, I’ll explain it by step:

    • Press the Windows Key (Button) and search for REGEDIT .
    • Browse to the location: HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsa
    • Locate the fipsalgorithmpolicy key and edit it by set its value to 0, or find the map with that name and disable it.

    If done, I think the error wouldn’t appear anymore.

    Q: Framerate dips down to 20 FPS or lower, and then comes back?
    A: This sounds like an issue with the CPU Affinity, you can set your affinity and see if the issue resolves.

    Ссылка на основную публикацию
    Adblock
    detector